001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.w3.ldp.testsuite.matcher; 019 020import java.util.regex.Pattern; 021 022import org.apache.commons.lang3.StringUtils; 023import org.hamcrest.BaseMatcher; 024import org.hamcrest.CustomTypeSafeMatcher; 025import org.hamcrest.Description; 026import org.hamcrest.Matcher; 027import org.jboss.resteasy.plugins.delegates.LinkDelegate; 028import org.w3.ldp.testsuite.http.MediaTypes; 029 030import javax.ws.rs.core.Link; 031 032/** 033 * Matcher collection to work with HttpHeaders. 034 */ 035public class HeaderMatchers { 036 037 private static final Pattern TURTLE_REGEX = Pattern.compile("^" + MediaTypes.TEXT_TURTLE + "\\s*(;|$)"); 038 /** 039 * Regular expression matching valid ETag values. 040 * 041 * @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19">HTTP 1.1: Section 14.19 - ETag</a> 042 */ 043 public final static String ETAG_REGEX = "^(W/)?\"([^\"]|\\\\\")*\"$"; 044 045 public static Matcher<String> headerPresent() { 046 return new BaseMatcher<String>() { 047 @Override 048 public boolean matches(Object item) { 049 return item != null && StringUtils.isNotBlank(item.toString()); 050 } 051 052 @Override 053 public void describeTo(Description description) { 054 description.appendText("set"); 055 } 056 }; 057 } 058 059 public static Matcher<String> headerNotPresent() { 060 return new BaseMatcher<String>() { 061 @Override 062 public boolean matches(Object item) { 063 return item == null || StringUtils.isBlank(item.toString()); 064 } 065 066 @Override 067 public void describeTo(Description description) { 068 description.appendText("absent or empty"); 069 } 070 }; 071 } 072 073 public static Matcher<String> isLink(String uri, String rel) { 074 final Link expected = Link.fromUri(uri).rel(rel).build(); 075 return new CustomTypeSafeMatcher<String>(String.format("a Link-Header to <%s> with rel='%s'", uri, rel)) { 076 @Override 077 protected boolean matchesSafely(String item) { 078 return expected.equals(new LinkDelegate().fromString(item)); 079 } 080 }; 081 } 082 083 084 public static Matcher<String> isValidEntityTag() { 085 return new CustomTypeSafeMatcher<String>("a valid EntityTag value as defined in RFC2616 section 14.19 (did you quote the value?)") { 086 /** 087 * Checks that the ETag value is present and valid as defined in RFC2616 088 * 089 * @param item 090 * the header value 091 * @return true only if the ETag is valid 092 * 093 * @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19">HTTP 1.1: Section 14.19 - ETag</a> 094 */ 095 @Override 096 protected boolean matchesSafely(String item) { 097 return item.trim().matches(ETAG_REGEX); 098 } 099 }; 100 } 101 102 /** 103 * Matcher testing a Content-Type response header's compatibility with 104 * JSON-LD (expects application/ld+json or application/json). 105 * 106 * @return the matcher 107 */ 108 public static Matcher<String> isJsonLdCompatibleContentType() { 109 return new CustomTypeSafeMatcher<String>("application/ld+json or application/json") { 110 @Override 111 protected boolean matchesSafely(String item) { 112 return item.equals(MediaTypes.APPLICATION_LD_JSON) || item.equals(MediaTypes.APPLICATION_JSON); 113 } 114 }; 115 } 116 117 /** 118 * Matcher testing a Content-Type response header's compatibility with 119 * Turtle (expects text/turtle). 120 * 121 * @return the matcher 122 */ 123 public static Matcher<String> isTurtleCompatibleContentType() { 124 return new CustomTypeSafeMatcher<String>("text/turtle") { 125 @Override 126 protected boolean matchesSafely(String item) { 127 return MediaTypes.TEXT_TURTLE.equals(item) 128 || TURTLE_REGEX.matcher(item).find(); 129 } 130 }; 131 } 132}