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 static org.apache.juneau.commons.utils.Utils.*;
020
021import org.apache.juneau.*;
022import org.apache.juneau.http.response.*;
023import org.apache.juneau.objecttools.*;
024import org.apache.juneau.parser.*;
025import org.apache.juneau.rest.*;
026
027/**
028 * Converter for enabling of {@link ObjectRest} support on response objects returned by a <c>@RestOp</c>-annotated method.
029 *
030 * <p>
031 * When enabled, objects in a POJO tree returned by the REST method can be addressed through additional URL path
032 * information.
033 *
034 * <p class='bjava'>
035 *    <jc>// Resource method on resource "http://localhost:8080/sample/addressBook"</jc>
036 *    <ja>@RestOp</ja>(method=<jsf>GET</jsf>, converters=Traversable.<jk>class</jk>)
037 *    <jk>public void</jk> doGet(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) {
038 *       <jk>return new</jk> AddressBook();
039 *    }
040 * </p>
041 *
042 * <h5 class='section'>See Also:</h5><ul>
043 *    <li class='jc'>{@link ObjectRest} - Additional information on addressing elements in a POJO tree using URL notation.
044 *    <li class='jm'>{@link org.apache.juneau.rest.RestOpContext.Builder#converters()} - Registering converters with REST resources.
045 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Converters">Converters</a>
046 * </ul>
047 */
048public class Traversable implements RestConverter {
049
050   @Override /* Overridden from RestConverter */
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 (nn(pathRemainder)) {
058         try {
059            BeanSession bs = req.getBeanSession();
060            var swap = bs.getClassMetaForObject(o).getSwap(bs);
061            if (nn(swap))
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            var 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}