001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.rest.converter;
018
019import org.apache.juneau.*;
020import org.apache.juneau.http.response.*;
021import org.apache.juneau.objecttools.*;
022import org.apache.juneau.parser.*;
023import org.apache.juneau.rest.*;
024import org.apache.juneau.swap.*;
025
026/**
027 * Converter for enabling of {@link ObjectRest} support on response objects returned by a <c>@RestOp</c>-annotated method.
028 *
029 * <p>
030 * When enabled, objects in a POJO tree returned by the REST method can be addressed through additional URL path
031 * information.
032 *
033 * <p class='bjava'>
034 *    <jc>// Resource method on resource "http://localhost:8080/sample/addressBook"</jc>
035 *    <ja>@RestOp</ja>(method=<jsf>GET</jsf>, converters=Traversable.<jk>class</jk>)
036 *    <jk>public void</jk> doGet(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) {
037 *       <jk>return new</jk> AddressBook();
038 *    }
039 * </p>
040 *
041 * <h5 class='section'>See Also:</h5><ul>
042 *    <li class='jc'>{@link ObjectRest} - Additional information on addressing elements in a POJO tree using URL notation.
043 *    <li class='jm'>{@link org.apache.juneau.rest.RestOpContext.Builder#converters()} - Registering converters with REST resources.
044 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Converters">Converters</a>
045 * </ul>
046 */
047public class Traversable implements RestConverter {
048
049   @Override /* RestConverter */
050   @SuppressWarnings({"rawtypes", "unchecked"})
051   public Object convert(RestRequest req, Object o) throws BasicHttpException, InternalServerError {
052      if (o == null)
053         return null;
054
055      String pathRemainder = req.getPathRemainder().orElse(null);
056
057      if (pathRemainder != null) {
058         try {
059            BeanSession bs = req.getBeanSession();
060            ObjectSwap swap = bs.getClassMetaForObject(o).getSwap(bs);
061            if (swap != null)
062               o = swap.swap(bs, o);
063            ReaderParser rp = req.getContent().getParserMatch().map(ParserMatch::getParser).filter(ReaderParser.class::isInstance).map(ReaderParser.class::cast).orElse(null);
064            ObjectRest or = ObjectRest.create(o, rp);
065            o = or.get(pathRemainder);
066         } catch (ObjectRestException e) {
067            throw new BasicHttpException(e.getStatus(), e);
068         } catch (Throwable t) {
069            throw new InternalServerError(t);
070         }
071      }
072
073      return o;
074   }
075}