public int TotalCount() { if (this.IsObjectCachedByID()) return (int) QueryHelper.stat_cache( CacheRegion(), OBJ_COUNT_CACHE_KEY, "SELECT COUNT(*) FROM " + TableName()); return (int) QueryHelper.stat("SELECT COUNT(*) FROM " + TableName()); }
@Override public final List<T> findListByProperty( final Object[] values, final SingularAttribute<T, ? extends Object>... properties) { final CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(persistentClass); final Root<T> root = criteriaQuery.from(persistentClass); criteriaQuery.select(root); final Object value = values[0]; final SingularAttribute<T, ? extends Object> property = properties[0]; Predicate condition; condition = QueryHelper.equalsIgnoreCaseIfStringPredicate(criteriaBuilder, root, value, property); if (values.length > 1) { for (int i = 1; i < properties.length; i++) { final SingularAttribute<T, ? extends Object> property2 = properties[i]; final Object value2 = values[i]; final Predicate condition2 = QueryHelper.equalsIgnoreCaseIfStringPredicate(criteriaBuilder, root, value2, property2); condition = criteriaBuilder.and(condition, condition2); } } criteriaQuery.where(condition); final TypedQuery<T> typedQuery = getEntityManager().createQuery(criteriaQuery); addCacheHints(typedQuery, "findListByProperty"); return typedQuery.getResultList(); }
public List List(int page, int size, String orderBy) { String sql = "SELECT * FROM " + TableName() + " "; if (StringUtils.isNotBlank(orderBy)) { sql += "ORDER BY " + orderBy; } return QueryHelper.query_slice(getClass(), sql, page, size); }
@SuppressWarnings("unchecked") public <T extends POJO> T Get(long id) { if (id <= 0) return null; String sql = "SELECT * FROM " + TableName() + " WHERE id = ?"; boolean cached = IsObjectCachedByID(); return (T) QueryHelper.read_cache(getClass(), cached ? CacheRegion() : null, id, sql, id); }
public boolean updateAttrs(String[] attrNames, Object[] attrValues) { int len = attrNames.length; List<String> kvs = new ArrayList<String>(len); for (String attr : attrNames) { kvs.add(attr + " = ?"); } String sql = "update " + TableName() + " set " + StringUtils.join(kvs, ',') + " where id = ?"; List<Object> vals = new ArrayList<Object>(); for (Object val : attrValues) { vals.add(val); } vals.add(getId()); int ret = QueryHelper.update(sql, vals.toArray()); try { if (ret > 0) { for (int i = 0; i < len; i++) { BeanUtils.setProperty(this, attrNames[i], attrValues[i]); } } else { return false; } } catch (Exception e) { return false; } return true; }
public ConditionQuery getTraceDownQuery() { if (traceDownConditionQuery != null) { return traceDownConditionQuery; } traceDownConditionQuery = (ConditionQuery) QueryHelper.wrapQueryEntity(getTraceDown()); return traceDownConditionQuery; }
public boolean Delete() { boolean dr = Evict(QueryHelper.update("DELETE FROM " + TableName() + " WHERE id = ?", getId()) == 1); if (dr) { CacheManager.evict(CacheRegion(), OBJ_COUNT_CACHE_KEY); } return dr; }
public boolean updateAttr(String attrName, Object attrValue) { String sql = "update " + TableName() + " set " + attrName + " = ? where id = ?"; int ret = QueryHelper.update(sql, attrValue, getId()); try { if (ret > 0) { BeanUtils.setProperty(this, attrName, attrValue); } else { return false; } } catch (Exception e) { return false; } return true; }
// 对这个cache的更新操作需要格外留意 public List IDs(String afterFrom, Object... params) { String tbl = TableName(); String cacheKey = afterFrom; for (Object obj : params) { cacheKey += obj; } String sql = "select id from " + tbl + " "; if (StringUtils.isNotBlank(afterFrom)) { sql += afterFrom; } else { cacheKey = "all" + cacheKey; } return QueryHelper.query_cache(Long.class, CacheRegion(), cacheKey, sql, params); }
protected List<? extends POJO> BatchGet(List<Long> ids) { if (ids == null || ids.size() == 0) return null; StringBuilder sql = new StringBuilder("SELECT * FROM " + TableName() + " WHERE id IN ("); for (int i = 1; i <= ids.size(); i++) { sql.append('?'); if (i < ids.size()) sql.append(','); } sql.append(')'); List<? extends POJO> beans = QueryHelper.query(getClass(), sql.toString(), ids.toArray(new Object[ids.size()])); if (IsObjectCachedByID()) { for (Object bean : beans) { CacheManager.set(CacheRegion(), ((POJO) bean).getId(), (Serializable) bean); } } return beans; }
private static long _InsertObject(POJO obj) { Map<String, Object> pojo_bean = obj.ListInsertableFields(); String[] fields = pojo_bean.keySet().toArray(new String[pojo_bean.size()]); StringBuilder sql = new StringBuilder("INSERT INTO "); sql.append(obj.TableName()); sql.append('('); for (int i = 0; i < fields.length; i++) { if (i > 0) sql.append(','); sql.append(fields[i]); } sql.append(") VALUES("); for (int i = 0; i < fields.length; i++) { if (i > 0) sql.append(','); sql.append('?'); } sql.append(')'); PreparedStatement ps = null; ResultSet rs = null; try { ps = QueryHelper.getConnection() .prepareStatement(sql.toString(), PreparedStatement.RETURN_GENERATED_KEYS); for (int i = 0; i < fields.length; i++) { ps.setObject(i + 1, pojo_bean.get(fields[i])); } ps.executeUpdate(); rs = ps.getGeneratedKeys(); return rs.next() ? rs.getLong(1) : -1; } catch (SQLException e) { throw new DBException(e); } finally { DbUtils.closeQuietly(rs); DbUtils.closeQuietly(ps); sql = null; fields = null; pojo_bean = null; } }
public <T extends POJO> T GetByAttr(String attrName, Object attrValue) { String sql = "SELECT * FROM " + TableName() + " WHERE " + attrName + " = ?"; return (T) QueryHelper.read(getClass(), sql, attrValue); }
/** * A collection of wavelets, local and remote, held in memory. * * @author [email protected] (Soren Lassen) */ public class WaveMap implements SearchProvider { /** * Helper class that allows to add basic sort and filter functionality to the search. * * @author [email protected] (Yuri Z.) */ private static class QueryHelper { @SuppressWarnings("serial") class InvalidQueryException extends Exception { public InvalidQueryException(String msg) { super(msg); } } /** * Unknown participantId used by {@link ASC_CREATOR_COMPARATOR} in case wave creator cannot be * found. */ static final ParticipantId UNKNOWN_CREATOR = ParticipantId.ofUnsafe("*****@*****.**"); /** Sorts search result in ascending order by LMT. */ static final Comparator<WaveViewData> ASC_LMT_COMPARATOR = new Comparator<WaveViewData>() { @Override public int compare(WaveViewData arg0, WaveViewData arg1) { long lmt0 = computeLmt(arg0); long lmt1 = computeLmt(arg1); return Long.signum(lmt0 - lmt1); } private long computeLmt(WaveViewData wave) { long lmt = -1; for (ObservableWaveletData wavelet : wave.getWavelets()) { // Skip non conversational wavelets. if (!IdUtil.isConversationalId(wavelet.getWaveletId())) { continue; } lmt = lmt < wavelet.getLastModifiedTime() ? wavelet.getLastModifiedTime() : lmt; } return lmt; } }; /** Sorts search result in descending order by LMT. */ static final Comparator<WaveViewData> DESC_LMT_COMPARATOR = new Comparator<WaveViewData>() { @Override public int compare(WaveViewData arg0, WaveViewData arg1) { return -ASC_LMT_COMPARATOR.compare(arg0, arg1); } }; /** Sorts search result in ascending order by creation time. */ static final Comparator<WaveViewData> ASC_CREATED_COMPARATOR = new Comparator<WaveViewData>() { @Override public int compare(WaveViewData arg0, WaveViewData arg1) { long time0 = computeCreatedTime(arg0); long time1 = computeCreatedTime(arg1); return Long.signum(time0 - time1); } private long computeCreatedTime(WaveViewData wave) { long creationTime = -1; for (ObservableWaveletData wavelet : wave.getWavelets()) { creationTime = creationTime < wavelet.getCreationTime() ? wavelet.getCreationTime() : creationTime; } return creationTime; } }; /** Sorts search result in descending order by creation time. */ static final Comparator<WaveViewData> DESC_CREATED_COMPARATOR = new Comparator<WaveViewData>() { @Override public int compare(WaveViewData arg0, WaveViewData arg1) { return -ASC_CREATED_COMPARATOR.compare(arg0, arg1); } }; /** Sorts search result in ascending order by creator */ static final Comparator<WaveViewData> ASC_CREATOR_COMPARATOR = new Comparator<WaveViewData>() { @Override public int compare(WaveViewData arg0, WaveViewData arg1) { ParticipantId creator0 = computeCreator(arg0); ParticipantId creator1 = computeCreator(arg1); return creator0.compareTo(creator1); } private ParticipantId computeCreator(WaveViewData wave) { for (ObservableWaveletData wavelet : wave.getWavelets()) { if (IdUtil.isConversationRootWaveletId(wavelet.getWaveletId())) { return wavelet.getCreator(); } } // If not found creator - compare with UNKNOWN_CREATOR; return UNKNOWN_CREATOR; } }; /** Sorts search result in descending order by creator */ static final Comparator<WaveViewData> DESC_CREATOR_COMPARATOR = new Comparator<WaveViewData>() { @Override public int compare(WaveViewData arg0, WaveViewData arg1) { return -ASC_CREATOR_COMPARATOR.compare(arg0, arg1); } }; /** Sorts search result by WaveId. */ static final Comparator<WaveViewData> ID_COMPARATOR = new Comparator<WaveViewData>() { @Override public int compare(WaveViewData arg0, WaveViewData arg1) { return arg0.getWaveId().compareTo(arg1.getWaveId()); } }; /** Orders using {@link ASCENDING_DATE_COMPARATOR}. */ static final Ordering<WaveViewData> ASC_LMT_ORDERING = Ordering.from(QueryHelper.ASC_LMT_COMPARATOR); /** Orders using {@link DESCENDING_DATE_COMPARATOR}. */ static final Ordering<WaveViewData> DESC_LMT_ORDERING = Ordering.from(QueryHelper.DESC_LMT_COMPARATOR); /** Orders using {@link ASC_CREATED_COMPARATOR}. */ static final Ordering<WaveViewData> ASC_CREATED_ORDERING = Ordering.from(QueryHelper.ASC_CREATED_COMPARATOR); /** Orders using {@link DESC_CREATED_COMPARATOR}. */ static final Ordering<WaveViewData> DESC_CREATED_ORDERING = Ordering.from(QueryHelper.DESC_CREATED_COMPARATOR); /** Orders using {@link ASC_CREATOR_COMPARATOR}. */ static final Ordering<WaveViewData> ASC_CREATOR_ORDERING = Ordering.from(QueryHelper.ASC_CREATOR_COMPARATOR); /** Orders using {@link DESC_CREATOR_COMPARATOR}. */ static final Ordering<WaveViewData> DESC_CREATOR_ORDERING = Ordering.from(QueryHelper.DESC_CREATOR_COMPARATOR); /** Default ordering is by LMT descending. */ static final Ordering<WaveViewData> DEFAULT_ORDERING = DESC_LMT_ORDERING; /** Valid search query types. */ enum TokenQueryType { IN("in"), ORDERBY("orderby"), WITH("with"), CREATOR("creator"); final String token; TokenQueryType(String token) { this.token = token; } String getToken() { return token; } private static final Map<String, TokenQueryType> reverseLookupMap = new HashMap<String, TokenQueryType>(); static { for (TokenQueryType type : TokenQueryType.values()) { reverseLookupMap.put(type.getToken(), type); } } static TokenQueryType fromToken(String token) { TokenQueryType qyeryToken = reverseLookupMap.get(token); if (qyeryToken == null) { throw new IllegalArgumentException("Illegal query param: " + token); } return reverseLookupMap.get(token); } static boolean hasToken(String token) { return reverseLookupMap.keySet().contains(token); } } /** Registered order by parameter types and corresponding orderings. */ enum OrderByValueType { DATEASC("dateasc", ASC_LMT_ORDERING), DATEDESC("datedesc", DESC_LMT_ORDERING), CREATEDASC("createdasc", ASC_CREATED_ORDERING), CREATEDDESC("createddesc", DESC_CREATED_ORDERING), CREATORASC("creatorasc", ASC_CREATOR_ORDERING), CREATORDESC("creatordesc", DESC_CREATOR_ORDERING); final String value; final Ordering<WaveViewData> ordering; OrderByValueType(String value, Ordering<WaveViewData> ordering) { this.value = value; this.ordering = ordering; } String getToken() { return value; } Ordering<WaveViewData> getOrdering() { return ordering; } private static final Map<String, OrderByValueType> reverseLookupMap = new HashMap<String, OrderByValueType>(); static { for (OrderByValueType type : OrderByValueType.values()) { reverseLookupMap.put(type.getToken(), type); } } static OrderByValueType fromToken(String token) { OrderByValueType orderByValue = reverseLookupMap.get(token); if (orderByValue == null) { throw new IllegalArgumentException("Illegal 'orderby' value: " + token); } return reverseLookupMap.get(token); } } private QueryHelper() {} /** Static factory method. */ static QueryHelper newQueryHelper() { return new QueryHelper(); } /** * Parses the search query. * * @param query the query. * @return the result map with query tokens. Never returns null. * @throws InvalidQueryException if the query contains invalid params. */ Map<TokenQueryType, Set<String>> parseQuery(String query) throws InvalidQueryException { Preconditions.checkArgument(query != null); query = query.trim(); // If query is empty - return. if (query.isEmpty()) { return Collections.emptyMap(); } String[] tokens = query.split("\\s+"); Map<TokenQueryType, Set<String>> tokensMap = Maps.newEnumMap(TokenQueryType.class); for (String token : tokens) { String[] pair = token.split(":"); if (pair.length != 2 || !TokenQueryType.hasToken(pair[0])) { String msg = "Invalid query param: " + token; throw new InvalidQueryException(msg); } String tokenValue = pair[1]; TokenQueryType tokenType = TokenQueryType.fromToken(pair[0]); // Verify the orderby param. if (tokenType.equals(TokenQueryType.ORDERBY)) { try { OrderByValueType.fromToken(tokenValue); } catch (IllegalArgumentException e) { String msg = "Invalid orderby query value: " + tokenValue; throw new InvalidQueryException(msg); } } Set<String> valuesPerToken = tokensMap.get(tokenType); if (valuesPerToken == null) { valuesPerToken = Sets.newLinkedHashSet(); tokensMap.put(tokenType, valuesPerToken); } valuesPerToken.add(tokenValue); } return tokensMap; } /** * Builds a list of participants to serve as the filter for the query. * * @param queryParams the query params. * @param queryType the filter for the query , i.e. 'with'. * @param localDomain the local domain of the logged in user. * @return the participants list for the filter. * @throws InvalidParticipantAddress if participant id passed to the query is invalid. */ static List<ParticipantId> buildValidatedParticipantIds( Map<QueryHelper.TokenQueryType, Set<String>> queryParams, QueryHelper.TokenQueryType queryType, String localDomain) throws InvalidParticipantAddress { Set<String> tokenSet = queryParams.get(queryType); List<ParticipantId> participants = null; if (tokenSet != null) { participants = Lists.newArrayListWithCapacity(tokenSet.size()); for (String token : tokenSet) { if (!token.isEmpty() && token.indexOf("@") == -1) { // If no domain was specified, assume that the participant is from the local domain. token = token + "@" + localDomain; } else if (token.equals("@")) { // "@" is a shortcut for the shared domain participant. token = "@" + localDomain; } ParticipantId otherUser = ParticipantId.of(token); participants.add(otherUser); } } else { participants = Collections.emptyList(); } return participants; } /** * Computes ordering for the search results. If none are specified - then returns the default * ordering. The resulting ordering is always compounded with ordering by wave id for stability. */ static Ordering<WaveViewData> computeSorter( Map<QueryHelper.TokenQueryType, Set<String>> queryParams) { Ordering<WaveViewData> ordering = null; Set<String> orderBySet = queryParams.get(QueryHelper.TokenQueryType.ORDERBY); if (orderBySet != null) { for (String orderBy : orderBySet) { QueryHelper.OrderByValueType orderingType = QueryHelper.OrderByValueType.fromToken(orderBy); if (ordering == null) { // Primary ordering. ordering = orderingType.getOrdering(); } else { // All other ordering are compounded to the primary one. ordering = ordering.compound(orderingType.getOrdering()); } } } else { ordering = QueryHelper.DEFAULT_ORDERING; } // For stability order also by wave id. ordering = ordering.compound(QueryHelper.ID_COMPARATOR); return ordering; } } private static final Log LOG = Log.get(WaveMap.class); private final QueryHelper queryHelper = QueryHelper.newQueryHelper(); /** The wavelets in a wave. */ private static final class Wave implements Iterable<WaveletContainer> { private class WaveletCreator<T extends WaveletContainer> implements Function<WaveletId, T> { private final WaveletContainer.Factory<T> factory; private final String waveDomain; public WaveletCreator(WaveletContainer.Factory<T> factory, String waveDomain) { this.factory = factory; this.waveDomain = waveDomain; } @Override public T apply(WaveletId waveletId) { return factory.create(notifiee, WaveletName.of(waveId, waveletId), waveDomain); } } private final WaveId waveId; /** Future providing already-existing wavelets in storage. */ private final ListenableFuture<ImmutableSet<WaveletId>> lookedupWavelets; private final ConcurrentMap<WaveletId, LocalWaveletContainer> localWavelets; private final ConcurrentMap<WaveletId, RemoteWaveletContainer> remoteWavelets; private final WaveletNotificationSubscriber notifiee; /** * Creates a wave. The {@code lookupWavelets} future is examined only when a query is first * made. */ public Wave( WaveId waveId, ListenableFuture<ImmutableSet<WaveletId>> lookedupWavelets, WaveletNotificationSubscriber notifiee, LocalWaveletContainer.Factory localFactory, RemoteWaveletContainer.Factory remoteFactory, String waveDomain) { this.waveId = waveId; this.lookedupWavelets = lookedupWavelets; this.notifiee = notifiee; this.localWavelets = new MapMaker() .makeComputingMap( new WaveletCreator<LocalWaveletContainer>(localFactory, waveDomain)); this.remoteWavelets = new MapMaker() .makeComputingMap( new WaveletCreator<RemoteWaveletContainer>(remoteFactory, waveDomain)); } @Override public Iterator<WaveletContainer> iterator() { return Iterators.unmodifiableIterator( Iterables.concat(localWavelets.values(), remoteWavelets.values()).iterator()); } public LocalWaveletContainer getLocalWavelet(WaveletId waveletId) throws WaveletStateException { return getWavelet(waveletId, localWavelets); } public RemoteWaveletContainer getRemoteWavelet(WaveletId waveletId) throws WaveletStateException { return getWavelet(waveletId, remoteWavelets); } public LocalWaveletContainer getOrCreateLocalWavelet(WaveletId waveletId) { return localWavelets.get(waveletId); } public RemoteWaveletContainer getOrCreateRemoteWavelet(WaveletId waveletId) { return remoteWavelets.get(waveletId); } private <T extends WaveletContainer> T getWavelet( WaveletId waveletId, ConcurrentMap<WaveletId, T> waveletsMap) throws WaveletStateException { ImmutableSet<WaveletId> storedWavelets; try { storedWavelets = FutureUtil.getResultOrPropagateException(lookedupWavelets, PersistenceException.class); } catch (PersistenceException e) { throw new WaveletStateException( "Failed to lookup wavelet " + WaveletName.of(waveId, waveletId), e); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new WaveletStateException( "Interrupted looking up wavelet " + WaveletName.of(waveId, waveletId), e); } // Since waveletsMap is a computing map, we must call containsKey(waveletId) // to tell if waveletId is mapped, we cannot test if get(waveletId) returns null. if (!storedWavelets.contains(waveletId) && !waveletsMap.containsKey(waveletId)) { return null; } else { T wavelet = waveletsMap.get(waveletId); Preconditions.checkNotNull(wavelet, "computingMap returned null"); return wavelet; } } } /** * Returns a future whose result is the ids of stored wavelets in the given wave. Any failure is * reported as a {@link PersistenceException}. */ private static ListenableFuture<ImmutableSet<WaveletId>> lookupWavelets( final WaveId waveId, final WaveletStore<?> waveletStore, Executor lookupExecutor) { ListenableFutureTask<ImmutableSet<WaveletId>> task = new ListenableFutureTask<ImmutableSet<WaveletId>>( new Callable<ImmutableSet<WaveletId>>() { @Override public ImmutableSet<WaveletId> call() throws PersistenceException { return waveletStore.lookup(waveId); } }); lookupExecutor.execute(task); return task; } private final ConcurrentMap<WaveId, Wave> waves; private final WaveletStore<?> store; @Inject public WaveMap( final DeltaAndSnapshotStore waveletStore, final WaveletNotificationSubscriber notifiee, final LocalWaveletContainer.Factory localFactory, final RemoteWaveletContainer.Factory remoteFactory, @Named(CoreSettings.WAVE_SERVER_DOMAIN) final String waveDomain) { // NOTE(anorth): DeltaAndSnapshotStore is more specific than necessary, but // helps Guice out. // TODO(soren): inject a proper executor (with a pool of configurable size) this.store = waveletStore; final Executor lookupExecutor = Executors.newSingleThreadExecutor(); waves = new MapMaker() .makeComputingMap( new Function<WaveId, Wave>() { @Override public Wave apply(WaveId waveId) { ListenableFuture<ImmutableSet<WaveletId>> lookedupWavelets = lookupWavelets(waveId, waveletStore, lookupExecutor); return new Wave( waveId, lookedupWavelets, notifiee, localFactory, remoteFactory, waveDomain); } }); } /** * Loads all wavelets from storage. * * @throws WaveletStateException if storage access fails. */ public void loadAllWavelets() throws WaveletStateException { try { ExceptionalIterator<WaveId, PersistenceException> itr = store.getWaveIdIterator(); while (itr.hasNext()) { WaveId waveId = itr.next(); lookupWavelets(waveId); } } catch (PersistenceException e) { throw new WaveletStateException("Failed to scan waves", e); } } @Override public Collection<WaveViewData> search( ParticipantId user, String query, int startAt, int numResults) { LOG.fine( "Search query '" + query + "' from user: "******" [" + startAt + ", " + (startAt + numResults - 1) + "]"); Map<QueryHelper.TokenQueryType, Set<String>> queryParams = null; try { queryParams = queryHelper.parseQuery(query); } catch (QueryHelper.InvalidQueryException e1) { // Invalid query param - stop and return empty search results. LOG.warning("Invalid Query. " + e1.getMessage()); return Collections.emptyList(); } List<ParticipantId> withParticipantIds = null; List<ParticipantId> creatorParticipantIds = null; try { String localDomain = user.getDomain(); // Build and validate. withParticipantIds = QueryHelper.buildValidatedParticipantIds( queryParams, QueryHelper.TokenQueryType.WITH, localDomain); creatorParticipantIds = QueryHelper.buildValidatedParticipantIds( queryParams, QueryHelper.TokenQueryType.CREATOR, localDomain); } catch (InvalidParticipantAddress e) { // Invalid address - stop and return empty search results. LOG.warning("Invalid participantId: " + e.getAddress() + " in query: " + query); return Collections.emptyList(); } // Maybe should be changed in case other folders in addition to 'inbox' are added. boolean isAllQuery = !queryParams.containsKey(QueryHelper.TokenQueryType.IN); // Must use a map with stable ordering, since indices are meaningful. Map<WaveId, WaveViewData> results = Maps.newLinkedHashMap(); for (Map.Entry<WaveId, Wave> entry : waves.entrySet()) { WaveId waveId = entry.getKey(); Wave wave = entry.getValue(); WaveViewData view = null; // Copy of the wave built up for search hits. for (WaveletContainer c : wave) { // TODO (Yuri Z.) This loop collects all the wavelets that match the // query, so the view is determined by the query. Instead we should // look at the user's wave view and determine if the view matches the query. ParticipantId sharedDomainParticipantId = c.getSharedDomainParticipant(); try { // TODO (Yuri Z.) Need to explore how to avoid this copy, e.g., by // moving parts of the matches() logic into a WaveletContainer method. ObservableWaveletData wavelet = c.copyWaveletData(); // Only filtering by participants is implemented for now. if (!matches( wavelet, user, sharedDomainParticipantId, withParticipantIds, creatorParticipantIds, isAllQuery)) { continue; } if (view == null) { view = WaveViewDataImpl.create(waveId); } // Just keep adding all the relevant wavelets in this wave. view.addWavelet(wavelet); } catch (WaveletStateException e) { LOG.warning("Failed to access wavelet " + c.getWaveletName(), e); } } // Filter out waves without conversational root wavelet from search result. if (WaveletDataUtil.hasConversationalRootWavelet(view)) { results.put(waveId, view); } } List<WaveViewData> searchResultslist = null; int searchResultSize = results.values().size(); // Check if we have enough results to return. if (searchResultSize < startAt) { searchResultslist = Collections.emptyList(); } else { int endAt = Math.min(startAt + numResults, searchResultSize); searchResultslist = QueryHelper.computeSorter(queryParams) .sortedCopy(results.values()) .subList(startAt, endAt); } LOG.info( "Search response to '" + query + "': " + searchResultslist.size() + " results, user: "******"Failed to look up wave " + waveId, e); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new WaveletStateException("Interrupted while looking up wave " + waveId, e); } } public LocalWaveletContainer getLocalWavelet(WaveletName waveletName) throws WaveletStateException { return waves.get(waveletName.waveId).getLocalWavelet(waveletName.waveletId); } public RemoteWaveletContainer getRemoteWavelet(WaveletName waveletName) throws WaveletStateException { return waves.get(waveletName.waveId).getRemoteWavelet(waveletName.waveletId); } public LocalWaveletContainer getOrCreateLocalWavelet(WaveletName waveletName) { return waves.get(waveletName.waveId).getOrCreateLocalWavelet(waveletName.waveletId); } public RemoteWaveletContainer getOrCreateRemoteWavelet(WaveletName waveletName) { return waves.get(waveletName.waveId).getOrCreateRemoteWavelet(waveletName.waveletId); } }
@Override public Collection<WaveViewData> search( ParticipantId user, String query, int startAt, int numResults) { LOG.fine( "Search query '" + query + "' from user: "******" [" + startAt + ", " + (startAt + numResults - 1) + "]"); Map<QueryHelper.TokenQueryType, Set<String>> queryParams = null; try { queryParams = queryHelper.parseQuery(query); } catch (QueryHelper.InvalidQueryException e1) { // Invalid query param - stop and return empty search results. LOG.warning("Invalid Query. " + e1.getMessage()); return Collections.emptyList(); } List<ParticipantId> withParticipantIds = null; List<ParticipantId> creatorParticipantIds = null; try { String localDomain = user.getDomain(); // Build and validate. withParticipantIds = QueryHelper.buildValidatedParticipantIds( queryParams, QueryHelper.TokenQueryType.WITH, localDomain); creatorParticipantIds = QueryHelper.buildValidatedParticipantIds( queryParams, QueryHelper.TokenQueryType.CREATOR, localDomain); } catch (InvalidParticipantAddress e) { // Invalid address - stop and return empty search results. LOG.warning("Invalid participantId: " + e.getAddress() + " in query: " + query); return Collections.emptyList(); } // Maybe should be changed in case other folders in addition to 'inbox' are added. boolean isAllQuery = !queryParams.containsKey(QueryHelper.TokenQueryType.IN); // Must use a map with stable ordering, since indices are meaningful. Map<WaveId, WaveViewData> results = Maps.newLinkedHashMap(); for (Map.Entry<WaveId, Wave> entry : waves.entrySet()) { WaveId waveId = entry.getKey(); Wave wave = entry.getValue(); WaveViewData view = null; // Copy of the wave built up for search hits. for (WaveletContainer c : wave) { // TODO (Yuri Z.) This loop collects all the wavelets that match the // query, so the view is determined by the query. Instead we should // look at the user's wave view and determine if the view matches the query. ParticipantId sharedDomainParticipantId = c.getSharedDomainParticipant(); try { // TODO (Yuri Z.) Need to explore how to avoid this copy, e.g., by // moving parts of the matches() logic into a WaveletContainer method. ObservableWaveletData wavelet = c.copyWaveletData(); // Only filtering by participants is implemented for now. if (!matches( wavelet, user, sharedDomainParticipantId, withParticipantIds, creatorParticipantIds, isAllQuery)) { continue; } if (view == null) { view = WaveViewDataImpl.create(waveId); } // Just keep adding all the relevant wavelets in this wave. view.addWavelet(wavelet); } catch (WaveletStateException e) { LOG.warning("Failed to access wavelet " + c.getWaveletName(), e); } } // Filter out waves without conversational root wavelet from search result. if (WaveletDataUtil.hasConversationalRootWavelet(view)) { results.put(waveId, view); } } List<WaveViewData> searchResultslist = null; int searchResultSize = results.values().size(); // Check if we have enough results to return. if (searchResultSize < startAt) { searchResultslist = Collections.emptyList(); } else { int endAt = Math.min(startAt + numResults, searchResultSize); searchResultslist = QueryHelper.computeSorter(queryParams) .sortedCopy(results.values()) .subList(startAt, endAt); } LOG.info( "Search response to '" + query + "': " + searchResultslist.size() + " results, user: " + user); // Memory management wise it's dangerous to return a sublist of a much // longer list, therefore, we return a 'defensive' copy. return ImmutableList.copyOf(searchResultslist); }
public List BatchGetByAttr(String attrName, Object attrValue) { String sql = "SELECT * FROM " + TableName() + " WHERE " + attrName + " = ?"; return QueryHelper.query(getClass(), sql, attrValue); }
public int TotalCount(String filter, Object... params) { return (int) QueryHelper.stat("SELECT COUNT(*) FROM " + TableName() + " WHERE " + filter, params); }
public List Filter(String filter, int page, int size) { String sql = "SELECT * FROM " + TableName() + " WHERE " + filter + " ORDER BY id DESC"; return QueryHelper.query_slice(getClass(), sql, page, size); }