<commit_before>package com.afrozaar.wordpress.wpapi.v2;

import com.afrozaar.wordpress.wpapi.v2.model.Link;
import com.afrozaar.wordpress.wpapi.v2.model.Post;
import com.afrozaar.wordpress.wpapi.v2.request.GetPostRequest;
import com.afrozaar.wordpress.wpapi.v2.request.Request;
import com.afrozaar.wordpress.wpapi.v2.request.SearchRequest;
import com.afrozaar.wordpress.wpapi.v2.request.UpdatePostRequest;
import com.afrozaar.wordpress.wpapi.v2.util.AuthUtil;
import com.afrozaar.wordpress.wpapi.v2.util.Two;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class Client implements Wordpress {
    private static final Logger LOG = LoggerFactory.getLogger(Client.class);

    private RestTemplate restTemplate = new RestTemplate(Arrays.asList(new MappingJackson2HttpMessageConverter()));
    private final Predicate<Link> next = link -> Strings.NEXT.equals(link.getRel());
    private final Predicate<Link> previous = link -> Strings.PREV.equals(link.getRel());

    public final String baseUrl;
    final private String username;
    final private String password;
    final private boolean debug;

    public Client(String baseUrl, String username, String password, boolean debug) {
        this.baseUrl = baseUrl;
        this.username = username;
        this.password = password;
        this.debug = debug;
    }

    @Override
    public Post getPost(Integer id) {
        final URI uri = GetPostRequest.newInstance().usingClient(this).buildAndExpand(id).toUri();
        final Two<String, String> authTuple = AuthUtil.authTuple(username, password);
        final RequestEntity<Post> request = RequestEntity.method(HttpMethod.GET, uri).header(authTuple.k, authTuple.v).body(null);
        final ResponseEntity<Post> exchange = restTemplate.exchange(request, Post.class);

        return exchange.getBody();
    }

    @Override
    public PagedResponse<Post> fetchPosts() {
        SearchRequest initial = SearchRequest.posts(); //TODO: need better 'default'
        return fetchPosts(initial);
    }

    @Override
    public PagedResponse<Post> fetchPosts(SearchRequest search) {
        final URI uri = search.forHost(baseUrl, CONTEXT).build().toUri();
        final Two<String, String> authTuple = AuthUtil.authTuple(username, password);
        final RequestEntity<Post[]> request = RequestEntity.method(HttpMethod.GET, uri).header(authTuple.k, authTuple.v).body(null);
        final ResponseEntity<Post[]> exchange = restTemplate.exchange(request, Post[].class);

        debugHeaders(exchange.getHeaders());

        final HttpHeaders headers = exchange.getHeaders();
        final List<Link> links = parseLinks(headers);
        final List<Post> posts = Arrays.asList(exchange.getBody());

        LOG.trace("{} returned {} posts.", uri, posts.size());

        return PagedResponse.Builder.<Post>aPagedResponse()
                .withPages(headers)
                .withPosts(posts)
                .withSelf(uri.toASCIIString())
                .withNext(link(links, next))
                .withPrevious(link(links, previous))
                .build();
    }

    @Override
    public Post updatePost(Post post) {
        final URI uri = UpdatePostRequest.forPost(post).forHost(baseUrl, CONTEXT).buildAndExpand(post.getId()).toUri();
        final Two<String, String> authTuple = AuthUtil.authTuple(username, password);
        final RequestEntity<Post> requestEntity = RequestEntity.put(uri).header(authTuple.k, authTuple.v).body(post);
        final ResponseEntity<Post> exchange = restTemplate.exchange(requestEntity, Post.class);

        debugHeaders(exchange.getHeaders());

        return exchange.getBody();
    }

    private Optional<String> link(List<Link> links, Predicate<? super Link> linkPredicate) {
        return links.stream()
                .filter(linkPredicate)
                .map(Link::getHref)
                .findFirst();
    }

    private void debugHeaders(HttpHeaders headers) {
        if (debug) {
            LOG.debug("Headers:");
            headers.entrySet().stream().forEach(entry -> LOG.debug("{} -> {}", entry.getKey(), entry.getValue()));
        }
    }


    public List<Link> parseLinks(HttpHeaders headers) {
        //Link -> [<http://johan-wp/wp-json/wp/v2/posts?page=2>; rel="next"]

        Optional<List<String>> linkHeader = Optional.ofNullable(headers.get(Strings.HEADER_LINK));<commit_msg>Introduce doExchange that takes the information required to call exchange using restTemplate.<commit_after>package com.afrozaar.wordpress.wpapi.v2;

import com.afrozaar.wordpress.wpapi.v2.model.Link;
import com.afrozaar.wordpress.wpapi.v2.model.Post;
import com.afrozaar.wordpress.wpapi.v2.request.GetPostRequest;
import com.afrozaar.wordpress.wpapi.v2.request.Request;
import com.afrozaar.wordpress.wpapi.v2.request.SearchRequest;
import com.afrozaar.wordpress.wpapi.v2.request.UpdatePostRequest;
import com.afrozaar.wordpress.wpapi.v2.util.AuthUtil;
import com.afrozaar.wordpress.wpapi.v2.util.Two;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class Client implements Wordpress {
    private static final Logger LOG = LoggerFactory.getLogger(Client.class);

    private RestTemplate restTemplate = new RestTemplate(Arrays.asList(new MappingJackson2HttpMessageConverter()));
    private final Predicate<Link> next = link -> Strings.NEXT.equals(link.getRel());
    private final Predicate<Link> previous = link -> Strings.PREV.equals(link.getRel());

    public final String baseUrl;
    final private String username;
    final private String password;
    final private boolean debug;

    public Client(String baseUrl, String username, String password, boolean debug) {
        this.baseUrl = baseUrl;
        this.username = username;
        this.password = password;
        this.debug = debug;
    }

    @Override
    public Post getPost(Integer id) {
        final URI uri = GetPostRequest.newInstance().usingClient(this).buildAndExpand(id).toUri();
        final ResponseEntity<Post> exchange = doExchange(HttpMethod.GET, uri, Post.class, null);

        return exchange.getBody();
    }

    @Override
    public PagedResponse<Post> fetchPosts() {
        SearchRequest initial = SearchRequest.posts(); //TODO: need better 'default'
        return fetchPosts(initial);
    }

    @Override
    public PagedResponse<Post> fetchPosts(SearchRequest search) {
        final URI uri = search.forHost(baseUrl, CONTEXT).build().toUri();
        final ResponseEntity<Post[]> exchange = doExchange(HttpMethod.GET, uri, Post[].class, null);

        final HttpHeaders headers = exchange.getHeaders();
        final List<Link> links = parseLinks(headers);
        final List<Post> posts = Arrays.asList(exchange.getBody());

        LOG.trace("{} returned {} posts.", uri, posts.size());

        return PagedResponse.Builder.<Post>aPagedResponse()
                .withPages(headers)
                .withPosts(posts)
                .withSelf(uri.toASCIIString())
                .withNext(link(links, next))
                .withPrevious(link(links, previous))
                .build();
    }

    @Override
    public Post updatePost(Post post) {
        final URI uri = UpdatePostRequest.forPost(post).forHost(baseUrl, CONTEXT).buildAndExpand(post.getId()).toUri();
        final ResponseEntity<Post> exchange = doExchange(HttpMethod.PUT, uri, Post.class, post);

        return exchange.getBody();
    }

    private <T> ResponseEntity<T> doExchange(HttpMethod method, URI uri, Class<T> typeRef, T body) {
        final Two<String, String> authTuple = AuthUtil.authTuple(username, password);
        final RequestEntity<T> entity = RequestEntity.method(method, uri).header(authTuple.k, authTuple.v).body(body);
        final ResponseEntity<T> exchange = restTemplate.exchange(entity, typeRef);
        debugHeaders(exchange.getHeaders());
        return exchange;
    }

    private Optional<String> link(List<Link> links, Predicate<? super Link> linkPredicate) {
        return links.stream()
                .filter(linkPredicate)
                .map(Link::getHref)
                .findFirst();
    }

    private void debugHeaders(HttpHeaders headers) {
        if (debug) {
            LOG.debug("Headers:");
            headers.entrySet().stream().forEach(entry -> LOG.debug("{} -> {}", entry.getKey(), entry.getValue()));
        }
    }


    public List<Link> parseLinks(HttpHeaders headers) {
        //Link -> [<http://johan-wp/wp-json/wp/v2/posts?page=2>; rel="next"]

        Optional<List<String>> linkHeader = Optional.ofNullable(headers.get(Strings.HEADER_LINK));
{'fraction_non_alphanumeric': 0.11774409732962161, 'fraction_numerical': 0.003093102381688834, 'mean_word_length': 3.5561296383278536, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '825058', 'n_tokens_mistral': 2803, 'n_tokens_neox': 2705, 'n_words': 552}