WAVE-311 Refactors some more, ensures Solr search result include user data wavelet.
Project: http://git-wip-us.apache.org/repos/asf/incubator-wave/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-wave/commit/deb18544 Tree: http://git-wip-us.apache.org/repos/asf/incubator-wave/tree/deb18544 Diff: http://git-wip-us.apache.org/repos/asf/incubator-wave/diff/deb18544 Branch: refs/heads/wave-0.4-rc6 Commit: deb185440a815fe6149a7083cac924d499d46e93 Parents: d566b91 Author: Yuri Zelikov <[email protected]> Authored: Tue Apr 15 21:59:14 2014 +0300 Committer: Yuri Zelikov <[email protected]> Committed: Wed Aug 27 19:17:55 2014 +0300 ---------------------------------------------------------------------- .../box/server/robots/OperationContextImpl.java | 26 +++++++------- .../box/server/robots/util/OperationUtil.java | 37 +++++++------------- .../waveserver/AbstractSearchProviderImpl.java | 12 ++++--- .../waveserver/SimpleSearchProviderImpl.java | 12 +++---- .../waveserver/SolrSearchProviderImpl.java | 20 +++++++++-- .../server/waveserver/SolrWaveIndexerImpl.java | 13 ++++--- src/org/waveprotocol/wave/model/id/IdUtil.java | 14 +++++++- 7 files changed, 76 insertions(+), 58 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/deb18544/src/org/waveprotocol/box/server/robots/OperationContextImpl.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/robots/OperationContextImpl.java b/src/org/waveprotocol/box/server/robots/OperationContextImpl.java index 7e4809e..03874ea 100644 --- a/src/org/waveprotocol/box/server/robots/OperationContextImpl.java +++ b/src/org/waveprotocol/box/server/robots/OperationContextImpl.java @@ -19,7 +19,6 @@ package org.waveprotocol.box.server.robots; -import static org.waveprotocol.box.server.robots.util.OperationUtil.buildUserDataWaveletId; import static org.waveprotocol.box.server.robots.util.RobotsUtil.createEmptyRobotWavelet; import com.google.common.base.Preconditions; @@ -37,27 +36,28 @@ import com.google.wave.api.event.EventSerializer; import com.google.wave.api.event.EventType; import com.google.wave.api.event.OperationErrorEvent; +import org.waveprotocol.box.common.Receiver; import org.waveprotocol.box.server.frontend.CommittedWaveletSnapshot; import org.waveprotocol.box.server.robots.util.ConversationUtil; import org.waveprotocol.box.server.robots.util.OperationUtil; import org.waveprotocol.box.server.waveserver.WaveServerException; import org.waveprotocol.box.server.waveserver.WaveletProvider; -import org.waveprotocol.box.common.Receiver; import org.waveprotocol.wave.model.conversation.Conversation; import org.waveprotocol.wave.model.conversation.ConversationBlip; import org.waveprotocol.wave.model.conversation.ObservableConversationView; +import org.waveprotocol.wave.model.id.IdUtil; +import org.waveprotocol.wave.model.id.InvalidIdException; +import org.waveprotocol.wave.model.id.WaveId; +import org.waveprotocol.wave.model.id.WaveletId; +import org.waveprotocol.wave.model.id.WaveletName; +import org.waveprotocol.wave.model.operation.wave.TransformedWaveletDelta; import org.waveprotocol.wave.model.schema.SchemaCollection; +import org.waveprotocol.wave.model.version.HashedVersion; import org.waveprotocol.wave.model.wave.ParticipantId; import org.waveprotocol.wave.model.wave.data.ObservableWaveletData; import org.waveprotocol.wave.model.wave.data.impl.ObservablePluggableMutableDocument; import org.waveprotocol.wave.model.wave.data.impl.WaveletDataImpl; import org.waveprotocol.wave.model.wave.opbased.OpBasedWavelet; -import org.waveprotocol.wave.model.operation.wave.TransformedWaveletDelta; -import org.waveprotocol.wave.model.id.InvalidIdException; -import org.waveprotocol.wave.model.id.WaveId; -import org.waveprotocol.wave.model.id.WaveletId; -import org.waveprotocol.wave.model.id.WaveletName; -import org.waveprotocol.wave.model.version.HashedVersion; import org.waveprotocol.wave.util.logging.Log; import java.util.Collections; @@ -111,7 +111,7 @@ public class OperationContextImpl implements OperationContext, OperationResults private final Map<WaveletName, WaveletName> tempWaveletNameMap = Maps.newHashMap(); /** Caches {@link ObservableConversationView}s */ private final Map<WaveletName, Map<ParticipantId, ObservableConversationView>> - openedConversations; + openedConversations; /** Used to create conversations. */ private final ConversationUtil conversationUtil; @@ -225,7 +225,7 @@ public class OperationContextImpl implements OperationContext, OperationResults // Open a wavelet from the server CommittedWaveletSnapshot snapshot = getWaveletSnapshot(waveletName, participant); if (snapshot == null) { - if (waveletName.waveletId.equals(buildUserDataWaveletId(participant))) { + if (waveletName.waveletId.equals(IdUtil.buildUserDataWaveletId(participant))) { // Usually the user data is created by the web client whenever user // opens a wavelet for the first time. However, if the wavelet is // fetched for the first time with Robot/Data API - user data should be @@ -234,7 +234,7 @@ public class OperationContextImpl implements OperationContext, OperationResults } else { throw new InvalidRequestException("Wavelet " + waveletName + " couldn't be retrieved"); } - + } else { ObservableWaveletData obsWavelet = FACTORY.create(snapshot.snapshot); wavelet = new RobotWaveletData(obsWavelet, snapshot.committedVersion); @@ -362,7 +362,7 @@ public class OperationContextImpl implements OperationContext, OperationResults @Override public CommittedWaveletSnapshot getWaveletSnapshot(WaveletName waveletName, ParticipantId participant) - throws InvalidRequestException { + throws InvalidRequestException { try { if (!waveletProvider.checkAccessPermission(waveletName, participant)) { throw new InvalidRequestException("Access rejected"); @@ -377,7 +377,7 @@ public class OperationContextImpl implements OperationContext, OperationResults @Override public void getDeltas(WaveletName waveletName, ParticipantId participant, HashedVersion fromVersion, HashedVersion toVersion, Receiver<TransformedWaveletDelta> receiver) - throws InvalidRequestException { + throws InvalidRequestException { try { if (!waveletProvider.checkAccessPermission(waveletName, participant)) { throw new InvalidRequestException("Access rejected"); http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/deb18544/src/org/waveprotocol/box/server/robots/util/OperationUtil.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/robots/util/OperationUtil.java b/src/org/waveprotocol/box/server/robots/util/OperationUtil.java index 5a13938..18f106d 100644 --- a/src/org/waveprotocol/box/server/robots/util/OperationUtil.java +++ b/src/org/waveprotocol/box/server/robots/util/OperationUtil.java @@ -38,7 +38,6 @@ import org.waveprotocol.box.server.waveserver.WaveletProvider; import org.waveprotocol.box.server.waveserver.WaveletProvider.SubmitRequestListener; import org.waveprotocol.wave.federation.Proto.ProtocolWaveletDelta; import org.waveprotocol.wave.model.conversation.ConversationView; -import org.waveprotocol.wave.model.id.IdConstants; import org.waveprotocol.wave.model.id.IdUtil; import org.waveprotocol.wave.model.id.InvalidIdException; import org.waveprotocol.wave.model.id.WaveId; @@ -85,7 +84,7 @@ public class OperationUtil { throws InvalidRequestException { Object parameter = operation.getParameter(property); Class<T> clazz = (Class<T>) property.clazz(); - if (parameter == null || !clazz.isInstance(parameter)) { + if ((parameter == null) || !clazz.isInstance(parameter)) { throw new InvalidRequestException("property " + property + " not found", operation); } return clazz.cast(parameter); @@ -120,7 +119,7 @@ public class OperationUtil { OperationRequest operation, ParamsProperty property, T defaultValue) { Object parameter = operation.getParameter(property); Class<T> clazz = (Class<T>) property.clazz(); - if (parameter != null && clazz.isInstance(parameter)) { + if ((parameter != null) && clazz.isInstance(parameter)) { return clazz.cast(parameter); } return defaultValue; @@ -168,7 +167,7 @@ public class OperationUtil { * Executes an {@link OperationRequest}. If the operation throws an * {@link InvalidRequestException} this exception will be used to construct an * error response in the {@link OperationContext}. - * + * * @param operation the operation to be executed. If the operation contains * {@link ParamsProperty.PROXYING_FOR} - then it will be taken in * account. @@ -210,11 +209,11 @@ public class OperationUtil { } } } - - + + /** * Appends proxyFor to the participant address. - * + * * @param proxyFor the proxyFor. * @param participant the participant to apply the proxyFor. * @return new participant instance in the format @@ -242,7 +241,7 @@ public class OperationUtil { /** * Computes participant ID using optional {@link ParamsProperty.PROXYING_FOR} * parameter. - * + * * @param operation the operation to be executed. * @param participant the base participant id. * @return new participant instance in the format @@ -260,24 +259,14 @@ public class OperationUtil { } catch (InvalidParticipantAddress e) { throw new InvalidRequestException( participant.getAddress() - + (proxyAddress != null ? "+" + proxyAddress : "" - + " is not a valid participant address"), operation); + + (proxyAddress != null ? "+" + proxyAddress : "" + + " is not a valid participant address"), operation); } } - - /** - * Builds user data wavelet id. - */ - public static WaveletId buildUserDataWaveletId(ParticipantId participant) { - WaveletId udwId = - WaveletId.of(participant.getDomain(), - IdUtil.join(IdConstants.USER_DATA_WAVELET_PREFIX, participant.getAddress())); - return udwId; - } - + /** * Builds the supplement model for a wave. - * + * * @param operation the operation. * @param context the operation context. * @param participant the viewer. @@ -292,7 +281,7 @@ public class OperationUtil { // TODO (Yuri Z.) Find a way to obtain an instance of IdGenerator and use it // to create udwId. - WaveletId udwId = buildUserDataWaveletId(participant); + WaveletId udwId = IdUtil.buildUserDataWaveletId(participant); String waveIdStr = OperationUtil.getRequiredParameter(operation, ParamsProperty.WAVE_ID); WaveId waveId = null; try { @@ -305,7 +294,7 @@ public class OperationUtil { PrimitiveSupplement udwState = WaveletBasedSupplement.create(udw); SupplementedWave supplement = - SupplementedWaveImpl.create(udwState, conversationView, participant, DefaultFollow.ALWAYS); + SupplementedWaveImpl.create(udwState, conversationView, participant, DefaultFollow.ALWAYS); return supplement; } http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/deb18544/src/org/waveprotocol/box/server/waveserver/AbstractSearchProviderImpl.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/waveserver/AbstractSearchProviderImpl.java b/src/org/waveprotocol/box/server/waveserver/AbstractSearchProviderImpl.java index f3d18c2..7d55812 100644 --- a/src/org/waveprotocol/box/server/waveserver/AbstractSearchProviderImpl.java +++ b/src/org/waveprotocol/box/server/waveserver/AbstractSearchProviderImpl.java @@ -20,9 +20,9 @@ package org.waveprotocol.box.server.waveserver; import com.google.common.base.Function; +import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import com.google.common.collect.Multimap; import org.waveprotocol.box.server.util.WaveletDataUtil; import org.waveprotocol.wave.model.id.IdUtil; @@ -37,10 +37,10 @@ import org.waveprotocol.wave.model.wave.data.WaveViewData; import org.waveprotocol.wave.model.wave.data.impl.WaveViewDataImpl; import org.waveprotocol.wave.util.logging.Log; -import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; +import java.util.Set; /** * Base implementation of search provider. @@ -72,15 +72,17 @@ public abstract class AbstractSearchProviderImpl implements SearchProvider { } } + // TODO (yurize) : Refactor this method. It does two things: filtering and + // building waves. protected LinkedHashMap<WaveId, WaveViewData> filterWavesViewBySearchCriteria( Function<ReadableWaveletData, Boolean> matchesFunction, - Multimap<WaveId, WaveletId> currentUserWavesView) { + LinkedHashMultimap<WaveId, WaveletId> currentUserWavesView) { // Must use a map with stable ordering, since indices are meaningful. LinkedHashMap<WaveId, WaveViewData> results = Maps.newLinkedHashMap(); // Loop over the user waves view. for (WaveId waveId : currentUserWavesView.keySet()) { - Collection<WaveletId> waveletIds = currentUserWavesView.get(waveId); + Set<WaveletId> waveletIds = currentUserWavesView.get(waveId); WaveViewData view = buildWaveViewData(waveId, waveletIds, matchesFunction, waveMap); Iterable<? extends ObservableWaveletData> wavelets = view.getWavelets(); boolean hasConversation = false; @@ -97,7 +99,7 @@ public abstract class AbstractSearchProviderImpl implements SearchProvider { return results; } - public static WaveViewData buildWaveViewData(WaveId waveId, Collection<WaveletId> waveletIds, + public static WaveViewData buildWaveViewData(WaveId waveId, Set<WaveletId> waveletIds, Function<ReadableWaveletData, Boolean> matchesFunction, WaveMap waveMap) { WaveViewData view = null; // Copy of the wave built up for search hits. http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/deb18544/src/org/waveprotocol/box/server/waveserver/SimpleSearchProviderImpl.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/waveserver/SimpleSearchProviderImpl.java b/src/org/waveprotocol/box/server/waveserver/SimpleSearchProviderImpl.java index 917a3b8..a1db671 100644 --- a/src/org/waveprotocol/box/server/waveserver/SimpleSearchProviderImpl.java +++ b/src/org/waveprotocol/box/server/waveserver/SimpleSearchProviderImpl.java @@ -20,9 +20,8 @@ package org.waveprotocol.box.server.waveserver; import com.google.common.base.Function; -import com.google.common.collect.HashMultimap; +import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Lists; -import com.google.common.collect.Multimap; import com.google.inject.Inject; import com.google.inject.name.Named; import com.google.wave.api.SearchResult; @@ -94,7 +93,8 @@ public class SimpleSearchProviderImpl extends AbstractSearchProviderImpl { return digester.generateSearchResult(user, query, null); } - Multimap<WaveId, WaveletId> currentUserWavesView = createWavesViewToFilter(user, isAllQuery); + LinkedHashMultimap<WaveId, WaveletId> currentUserWavesView = + createWavesViewToFilter(user, isAllQuery); Function<ReadableWaveletData, Boolean> filterWaveletsFunction = createFilterWaveletsFunction(user, isAllQuery, withParticipantIds, creatorParticipantIds); @@ -110,10 +110,10 @@ public class SimpleSearchProviderImpl extends AbstractSearchProviderImpl { return digester.generateSearchResult(user, query, searchResult); } - private Multimap<WaveId, WaveletId> createWavesViewToFilter(final ParticipantId user, + private LinkedHashMultimap<WaveId, WaveletId> createWavesViewToFilter(final ParticipantId user, final boolean isAllQuery) { - Multimap<WaveId, WaveletId> currentUserWavesView; - currentUserWavesView = HashMultimap.create(); + LinkedHashMultimap<WaveId, WaveletId> currentUserWavesView; + currentUserWavesView = LinkedHashMultimap.create(); currentUserWavesView.putAll(waveViewProvider.retrievePerUserWaveView(user)); if (isAllQuery) { // If it is the "all" query - we need to include also waves view of the http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/deb18544/src/org/waveprotocol/box/server/waveserver/SolrSearchProviderImpl.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/waveserver/SolrSearchProviderImpl.java b/src/org/waveprotocol/box/server/waveserver/SolrSearchProviderImpl.java index fb45f3f..6eb91cd 100644 --- a/src/org/waveprotocol/box/server/waveserver/SolrSearchProviderImpl.java +++ b/src/org/waveprotocol/box/server/waveserver/SolrSearchProviderImpl.java @@ -22,7 +22,6 @@ package org.waveprotocol.box.server.waveserver; import com.google.common.base.Function; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Lists; -import com.google.common.collect.Multimap; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -36,6 +35,8 @@ import org.apache.commons.httpclient.URI; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.http.HttpStatus; import org.waveprotocol.box.server.CoreSettings; +import org.waveprotocol.wave.model.id.IdConstants; +import org.waveprotocol.wave.model.id.IdUtil; import org.waveprotocol.wave.model.id.WaveId; import org.waveprotocol.wave.model.id.WaveletId; import org.waveprotocol.wave.model.id.WaveletName; @@ -50,6 +51,7 @@ import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Set; import java.util.regex.Pattern; /** @@ -141,7 +143,7 @@ public class SolrSearchProviderImpl extends AbstractSearchProviderImpl { // added. final boolean isAllQuery = isAllQuery(query); - Multimap<WaveId, WaveletId> currentUserWavesView = LinkedHashMultimap.create(); + LinkedHashMultimap<WaveId, WaveletId> currentUserWavesView = LinkedHashMultimap.create(); if (numResults > 0) { @@ -201,6 +203,8 @@ public class SolrSearchProviderImpl extends AbstractSearchProviderImpl { } } + ensureWavesHaveUserDataWavelet(currentUserWavesView, user); + Function<ReadableWaveletData, Boolean> matchesFunction = new Function<ReadableWaveletData, Boolean>() { @@ -232,6 +236,18 @@ public class SolrSearchProviderImpl extends AbstractSearchProviderImpl { return digester.generateSearchResult(user, query, searchResult); } + private void ensureWavesHaveUserDataWavelet( + LinkedHashMultimap<WaveId, WaveletId> currentUserWavesView, ParticipantId user) { + WaveletId udw = + WaveletId.of(user.getDomain(), + IdUtil.join(IdConstants.USER_DATA_WAVELET_PREFIX, user.getAddress())); + Set<WaveId> waveIds = currentUserWavesView.keySet(); + for (WaveId waveId : waveIds) { + Set<WaveletId> waveletIds = currentUserWavesView.get(waveId); + waveletIds.add(udw); + } + } + public static boolean isAllQuery(String query) { return !IN_PATTERN.matcher(query).find(); } http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/deb18544/src/org/waveprotocol/box/server/waveserver/SolrWaveIndexerImpl.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/box/server/waveserver/SolrWaveIndexerImpl.java b/src/org/waveprotocol/box/server/waveserver/SolrWaveIndexerImpl.java index 8c471ef..3a2fcd0 100644 --- a/src/org/waveprotocol/box/server/waveserver/SolrWaveIndexerImpl.java +++ b/src/org/waveprotocol/box/server/waveserver/SolrWaveIndexerImpl.java @@ -76,7 +76,7 @@ import java.util.logging.Level; */ @Singleton public class SolrWaveIndexerImpl extends AbstractWaveIndexer implements WaveBus.Subscriber, - PerUserWaveViewBus.Listener { +PerUserWaveViewBus.Listener { private static final Log LOG = Log.get(SolrWaveIndexerImpl.class); @@ -232,8 +232,7 @@ public class SolrWaveIndexerImpl extends AbstractWaveIndexer implements WaveBus. private void updateIndex(ReadableWaveletData wavelet) throws IndexException { Preconditions.checkNotNull(wavelet); - boolean isUserDataWavelet = IdUtil.isUserDataWavelet(wavelet.getWaveletId()); - if (!(IdUtil.isConversationRootWaveletId(wavelet.getWaveletId()) || isUserDataWavelet)) { + if (!IdUtil.isConversationalId(wavelet.getWaveletId())) { return; } @@ -250,7 +249,7 @@ public class SolrWaveIndexerImpl extends AbstractWaveIndexer implements WaveBus. for (String docName : wavelet.getDocumentIds()) { ReadableBlipData document = wavelet.getDocument(docName); - if (!(IdUtil.isBlipId(docName) || isUserDataWavelet)) { + if (!IdUtil.isBlipId(docName)) { continue; } @@ -425,9 +424,9 @@ public class SolrWaveIndexerImpl extends AbstractWaveIndexer implements WaveBus. GetMethod getMethod = new GetMethod(); try { getMethod - .setURI(new URI(SolrSearchProviderImpl.SOLR_BASE_URL + "/update?wt=json" - + "&stream.body=<delete><query>" + SolrSearchProviderImpl.Q + "</query></delete>", - false)); + .setURI(new URI(SolrSearchProviderImpl.SOLR_BASE_URL + "/update?wt=json" + + "&stream.body=<delete><query>" + SolrSearchProviderImpl.Q + "</query></delete>", + false)); HttpClient httpClient = new HttpClient(); int statusCode = httpClient.executeMethod(getMethod); http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/deb18544/src/org/waveprotocol/wave/model/id/IdUtil.java ---------------------------------------------------------------------- diff --git a/src/org/waveprotocol/wave/model/id/IdUtil.java b/src/org/waveprotocol/wave/model/id/IdUtil.java index 6868c80..6549995 100644 --- a/src/org/waveprotocol/wave/model/id/IdUtil.java +++ b/src/org/waveprotocol/wave/model/id/IdUtil.java @@ -19,6 +19,8 @@ package org.waveprotocol.wave.model.id; +import org.waveprotocol.wave.model.wave.ParticipantId; + /** * This class holds useful utilities for ids. @@ -124,6 +126,16 @@ public class IdUtil implements IdConstants { } /** + * Builds user data wavelet id. + */ + public static WaveletId buildUserDataWaveletId(ParticipantId participant) { + WaveletId udwId = + WaveletId.of(participant.getDomain(), + IdUtil.join(IdConstants.USER_DATA_WAVELET_PREFIX, participant.getAddress())); + return udwId; + } + + /** * Gets the address that a user data wavelet ID is for. * * @return UDW address, or {@code null} if the ID is not a user data wavelet @@ -131,7 +143,7 @@ public class IdUtil implements IdConstants { */ public static final String getUserDataWaveletAddress(WaveletId waveletId) { String[] parts = split(waveletId.getId()); - if (parts.length != 2 || !parts[0].equals(USER_DATA_WAVELET_PREFIX)) { + if ((parts.length != 2) || !parts[0].equals(USER_DATA_WAVELET_PREFIX)) { return null; } return parts[1];
