+ For further API reference and developer documentation, see the + Spring Integration Reference Documentation. + That documentation contains more detailed, developer-targeted + descriptions, with conceptual overviews, definitions of terms, + workarounds, and working code examples. +
+ ++ If you are interested in commercial training, consultancy, and + support for Spring Integration, please visit + http://spring.io +
+When using a {@code TweetData} directly in the expression, it is not necessary + * to include the package: + * {@code "new TweetData("test").withMedia(headers.mediaResource).displayCoordinates(true)")}. + * @param tweetDataExpression The expression. + * @since 4.0 + */ + public void setTweetDataExpression(Expression tweetDataExpression) { + this.tweetDataExpression = tweetDataExpression; + } + + public void setIntegrationEvaluationContext(EvaluationContext evaluationContext) { + this.evaluationContext = evaluationContext; + } + + @Override + protected void onInit() throws Exception { + super.onInit(); + + if (this.evaluationContext == null) { + this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(getBeanFactory()); + + TypeLocator typeLocator = this.evaluationContext.getTypeLocator(); + if (typeLocator instanceof StandardTypeLocator) { + /* + * Register the twitter api package so they don't need a FQCN for TweetData. + */ + ((StandardTypeLocator) typeLocator).registerImport("org.springframework.social.twitter.api"); + } + } + } + + @Override + protected void handleMessageInternal(Message> message) throws Exception { + Object value; + if (this.tweetDataExpression != null) { + value = this.tweetDataExpression.getValue(this.evaluationContext, message); + } + else { + value = message.getPayload(); + } + Assert.notNull(value, "The tweetData cannot evaluate to 'null'."); + + TweetData tweetData = null; + + if (value instanceof TweetData) { + tweetData = (TweetData) value; + } + else if (value instanceof Tweet) { + tweetData = new TweetData(((Tweet) value).getText()); + } + else if (value instanceof String) { + tweetData = new TweetData((String) value); + } + else { + throw new MessageHandlingException(message, "Unsupported tweetData: " + value); + } + + this.twitter.timelineOperations().updateStatus(tweetData); + } + +} diff --git a/spring-integration-social-twitter/src/main/java/org/springframework/integration/twitter/outbound/TwitterSearchOutboundGateway.java b/spring-integration-social-twitter/src/main/java/org/springframework/integration/twitter/outbound/TwitterSearchOutboundGateway.java new file mode 100644 index 0000000..6ecf10c --- /dev/null +++ b/spring-integration-social-twitter/src/main/java/org/springframework/integration/twitter/outbound/TwitterSearchOutboundGateway.java @@ -0,0 +1,160 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.twitter.outbound; + +import java.util.Collections; +import java.util.List; + +import org.springframework.expression.EvaluationContext; +import org.springframework.expression.Expression; +import org.springframework.expression.TypeLocator; +import org.springframework.expression.spel.support.StandardTypeLocator; +import org.springframework.integration.expression.ExpressionUtils; +import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; +import org.springframework.integration.twitter.core.TwitterHeaders; +import org.springframework.messaging.Message; +import org.springframework.social.twitter.api.SearchParameters; +import org.springframework.social.twitter.api.SearchResults; +import org.springframework.social.twitter.api.Tweet; +import org.springframework.social.twitter.api.Twitter; +import org.springframework.util.Assert; + +/** + * The {@link AbstractReplyProducingMessageHandler} implementation to perform request/reply + * Twitter search with {@link SearchParameters} as the result of {@link #searchArgsExpression} + * expression evaluation. + * + * @author Gary Russell + */ +public class TwitterSearchOutboundGateway extends AbstractReplyProducingMessageHandler { + + private static final int DEFAULT_PAGE_SIZE = 20; + + private final Twitter twitter; + + private volatile Expression searchArgsExpression; + + private volatile EvaluationContext evaluationContext; + + public TwitterSearchOutboundGateway(Twitter twitter) { + Assert.notNull(twitter, "'twitter' must not be null"); + this.twitter = twitter; + } + + /** + * An expression that is used to build the search; must resolve to a + * {@code SearchParameters} object, or a + * {@link String}, in which case the default page size of 20 is applied, + * or a list of up to 4 arguments, such as + * {@code "{payload, headers.pageSize, headers.sinceId, headers.maxId}"}. + * The first (required) argument must resolve to a String (query), the + * optional arguments must resolve to an Number and represent the + * page size, sinceId, and maxId respectively. Refer to the 'Spring + * Social Twitter' documentation for more details. + *
When using a {@code SearchParameters} directly, it is not necessary + * to include the package: {@code "new SearchParameters("#foo").count(20)")}. + *
Default: {@code "payload"}.
+ * @param searchArgsExpression The expression.
+ */
+ public void setSearchArgsExpression(Expression searchArgsExpression) {
+ Assert.notNull(searchArgsExpression, "'searchArgsExpression' must not be null");
+ this.searchArgsExpression = searchArgsExpression;
+ }
+
+ public void setIntegrationEvaluationContext(EvaluationContext evaluationContext) {
+ this.evaluationContext = evaluationContext;
+ }
+
+ @Override
+ public String getComponentType() {
+ return "twitter:search-outbound-gateway";
+ }
+
+ protected Twitter getTwitter() {
+ return this.twitter;
+ }
+
+ @Override
+ protected void doInit() {
+ super.doInit();
+ if (this.evaluationContext == null) {
+ this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(getBeanFactory());
+ TypeLocator typeLocator = this.evaluationContext.getTypeLocator();
+ if (typeLocator instanceof StandardTypeLocator) {
+ /*
+ * Register the twitter api package so they don't need a FQCN for SearchParameters.
+ */
+ ((StandardTypeLocator) typeLocator).registerImport("org.springframework.social.twitter.api");
+ }
+ }
+ }
+
+ @Override
+ protected Object handleRequestMessage(Message> requestMessage) {
+ Object args;
+ if (this.searchArgsExpression != null) {
+ args = this.searchArgsExpression.getValue(this.evaluationContext, requestMessage);
+ }
+ else {
+ args = requestMessage.getPayload();
+ }
+ Assert.notNull(args, "The twitter search expression cannot evaluate to 'null'.");
+ SearchParameters searchParameters;
+ if (args instanceof SearchParameters) {
+ searchParameters = (SearchParameters) args;
+ }
+ else if (args instanceof String) {
+ searchParameters = new SearchParameters((String) args).count(DEFAULT_PAGE_SIZE);
+ }
+ else if (args instanceof List) {
+ List> list = (List>) args;
+ Assert.isTrue(list.size() > 0 && list.size() < 5, "Between 1 and 4 search arguments are required");
+ Assert.isInstanceOf(String.class, list.get(0), "The first search argument (query) must be a String");
+ searchParameters = new SearchParameters((String) list.get(0));
+ if (list.size() > 1) {
+ Assert.isInstanceOf(Number.class, list.get(1),
+ "The second search argument (pageSize) must be a Number");
+ searchParameters.count(((Number) list.get(1)).intValue());
+ if (list.size() > 2) {
+ Assert.isInstanceOf(Number.class, list.get(2),
+ "The third search argument (sinceId) must be a Number");
+ searchParameters.sinceId(((Number) list.get(2)).longValue());
+ }
+ if (list.size() > 3) {
+ Assert.isInstanceOf(Number.class, list.get(3),
+ "The fourth search argument (maxId) must be a Number");
+ searchParameters.maxId(((Number) list.get(3)).longValue());
+ }
+ }
+ }
+ else {
+ throw new IllegalArgumentException(
+ "Search Expression must evaluate to a 'SearchParameters', 'String' or 'List'.");
+ }
+ SearchResults results = this.getTwitter().searchOperations().search(searchParameters);
+ if (results != null) {
+ List