### Question:
CacheControlHeaderProvider implements HeaderDelegate<CacheControl> { public CacheControl fromString(String c) { boolean isPrivate = false; List<String> privateFields = new ArrayList<>(); boolean noCache = false; List<String> noCacheFields = new ArrayList<>(); boolean noStore = false; boolean noTransform = false; boolean mustRevalidate = false; boolean proxyRevalidate = false; int maxAge = -1; int sMaxAge = -1; Map<String, String> extensions = new HashMap<>(); String[] tokens = getTokens(c); for (String rawToken : tokens) { String token = rawToken.trim(); if (token.startsWith(MAX_AGE)) { maxAge = Integer.parseInt(token.substring(MAX_AGE.length() + 1)); } else if (token.startsWith(SMAX_AGE)) { sMaxAge = Integer.parseInt(token.substring(SMAX_AGE.length() + 1)); } else if (token.startsWith(PUBLIC)) { } else if (token.startsWith(NO_STORE)) { noStore = true; } else if (token.startsWith(NO_TRANSFORM)) { noTransform = true; } else if (token.startsWith(MUST_REVALIDATE)) { mustRevalidate = true; } else if (token.startsWith(PROXY_REVALIDATE)) { proxyRevalidate = true; } else if (token.startsWith(PRIVATE)) { isPrivate = true; addFields(privateFields, token); } else if (token.startsWith(NO_CACHE)) { noCache = true; addFields(noCacheFields, token); } else { String[] extPair = token.split("="); String value = extPair.length == 2 ? extPair[1] : ""; extensions.put(extPair[0], value); } } CacheControl cc = new CacheControl(); cc.setMaxAge(maxAge); cc.setSMaxAge(sMaxAge); cc.setPrivate(isPrivate); cc.getPrivateFields().addAll(privateFields); cc.setMustRevalidate(mustRevalidate); cc.setProxyRevalidate(proxyRevalidate); cc.setNoCache(noCache); cc.getNoCacheFields().addAll(noCacheFields); cc.setNoStore(noStore); cc.setNoTransform(noTransform); cc.getCacheExtension().putAll(extensions); return cc; }  CacheControl fromString(String c); String toString(CacheControl c); static final String CACHE_CONTROL_SEPARATOR_PROPERTY; }### Answer:
@Test public void testFromComplexStringWithSemicolon() { CacheControlHeaderProvider cp = new CacheControlHeaderProvider() { protected Message getCurrentMessage() { Message m = new MessageImpl(); m.put(CacheControlHeaderProvider.CACHE_CONTROL_SEPARATOR_PROPERTY, ";"); return m; } }; CacheControl c = cp.fromString( "private=\"foo\";no-cache=\"bar\";no-store;no-transform;" + "must-revalidate;proxy-revalidate;max-age=2;s-maxage=3"); assertTrue(c.isPrivate() && c.isNoStore() && c.isMustRevalidate() && c.isProxyRevalidate() && c.isNoCache()); assertTrue(c.isNoTransform() && c.getNoCacheFields().size() == 1 && c.getPrivateFields().size() == 1); assertEquals("foo", c.getPrivateFields().get(0)); assertEquals("bar", c.getNoCacheFields().get(0)); }
@Test(expected = InternalServerErrorException.class) public void testInvalidSeparator() { CacheControlHeaderProvider cp = new CacheControlHeaderProvider() { protected Message getCurrentMessage() { Message m = new MessageImpl(); m.put(CacheControlHeaderProvider.CACHE_CONTROL_SEPARATOR_PROPERTY, "(e+)+"); return m; } }; cp.fromString("no-store"); }