001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.rest.client;
014
015import java.io.*;
016import java.util.regex.*;
017
018/**
019 * Used to find regular expression matches in REST responses made through {@link RestCall}.
020 *
021 * <p>
022 * Response patterns are applied to REST calls through the {@link RestCall#responsePattern(ResponsePattern)} method.
023 *
024 * <h5 class='section'>Example:</h5>
025 *
026 * This example shows how to use a response pattern finder to find and capture patterns for <js>"x=number"</js> and
027 * <js>"y=string"</js> from a response body.
028 * <p class='bcode w800'>
029 *    <jk>final</jk> List&lt;Number&gt; xList = <jk>new</jk> ArrayList&lt;Number&gt;();
030 *    <jk>final</jk> List&lt;String&gt; yList = <jk>new</jk> ArrayList&lt;String&gt;();
031 *
032 *    restClient.doGet(<jsf>URL</jsf>)
033 *       .addResponsePattern(
034 *          <jk>new</jk> ResponsePattern(<js>"x=(\\d+)"</js>) {
035 *             <ja>@Override</ja>
036 *             <jk>public void</jk> onMatch(RestCall restCall, Matcher m) <jk>throws</jk> RestCallException {
037 *                xList.add(Integer.<jsm>parseInt</jsm>(m.group(1)));
038 *             }
039 *             <ja>@Override</ja>
040 *             <jk>public void</jk> onNoMatch(RestCall restCall) <jk>throws</jk> RestCallException {
041 *                <jk>throw new</jk> RestCallException(<js>"No X's found!"</js>);
042 *             }
043 *          }
044 *       )
045 *       .addResponsePattern(
046 *          <jk>new</jk> ResponsePattern(<js>"y=(\\S+)"</js>) {
047 *             <ja>@Override</ja>
048 *             <jk>public void</jk> onMatch(RestCall restCall, Matcher m) <jk>throws</jk> RestCallException {
049 *                yList.add(m.group(1));
050 *             }
051 *             <ja>@Override</ja>
052 *             <jk>public void</jk> onNoMatch(RestCall restCall) <jk>throws</jk> RestCallException {
053 *                <jk>throw new</jk> RestCallException(<js>"No Y's found!"</js>);
054 *             }
055 *          }
056 *       )
057 *       .run();
058 * </p>
059 *
060 * <ul class='notes'>
061 *    <li>
062 *       Using response patterns does not affect the functionality of any of the other methods
063 *       used to retrieve the response such as {@link RestCall#getResponseAsString()} or {@link RestCall#getResponse(Class)}.
064 *       <br>HOWEVER, if you want to retrieve the entire text of the response from inside the match methods, use
065 *       {@link RestCall#getCapturedResponse()} since this method will not absorb the response for those other methods.
066 *    <li>
067 *       Response pattern methods are NOT executed if a REST exception occurs during the request.
068 *    <li>
069 *       The {@link RestCall#successPattern(String)} and {@link RestCall#failurePattern(String)} methods use instances
070 *       of this class to throw {@link RestCallException RestCallExceptions} when success patterns are not found or
071 *       failure patterns are found.
072 *    <li>
073 *       {@link ResponsePattern} objects are reusable and thread-safe.
074 * </ul>
075 *
076 * @deprecated Use new methods provided on {@link org.apache.juneau.rest.client2.RestResponse} class.
077 */
078@Deprecated
079public abstract class ResponsePattern {
080
081   private Pattern pattern;
082
083   /**
084    * Constructor.
085    *
086    * @param pattern Regular expression pattern.
087    */
088   public ResponsePattern(String pattern) {
089      this.pattern = Pattern.compile(pattern);
090   }
091
092   void match(RestCall rc) throws RestCallException {
093      try {
094         Matcher m = pattern.matcher(rc.getCapturedResponse());
095         boolean found = false;
096         while (m.find()) {
097            onMatch(rc, m);
098            found = true;
099         }
100         if (! found)
101            onNoMatch(rc);
102      } catch (IOException e) {
103         throw new RestCallException(e);
104      }
105   }
106
107   /**
108    * Returns the pattern passed in through the constructor.
109    *
110    * @return The pattern passed in through the constructor.
111    */
112   protected String getPattern() {
113      return pattern.pattern();
114   }
115
116   /**
117    * Instances can override this method to handle when a regular expression pattern matches on the output.
118    *
119    * <p>
120    * This method is called once for every pattern match that occurs in the response text.
121    *
122    * @param rc The {@link RestCall} that this pattern finder is being used on.
123    * @param m The regular expression {@link Matcher}.  Can be used to retrieve group matches in the pattern.
124    * @throws RestCallException Instances can throw an exception if a failure condition is detected.
125    */
126   public void onMatch(RestCall rc, Matcher m) throws RestCallException {}
127
128   /**
129    * Instances can override this method to handle when a regular expression pattern doesn't match on the output.
130    *
131    * @param rc The {@link RestCall} that this pattern finder is being used on.
132    * @throws RestCallException Instances can throw an exception if a failure condition is detected.
133    */
134   public void onNoMatch(RestCall rc) throws RestCallException {}
135}