/*
* Copyright 2008-2014 the original author or authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kaleidofoundry.core;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import junit.framework.Assert;
import org.junit.Test;
import org.kaleidofoundry.core.util.StringHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* simple sample for using regexp
*
* @author jraduget
*/
public class RegExpSample extends Assert {
static final Logger LOGGER = LoggerFactory.getLogger(RegExpSample.class);
/**
* simple sample enum of uri type and regExp
*/
public enum ResourceUriEnum {
/**
* <ul>
* <li>classpath:/filename</li>
* <li>classpath:/path/filename</li>
* <li>classpath:/directory1/directory2/filename</li>
* </ul>
*/
classpath("/((PATH)/(FILENAME))|/(FILENAME)"),
/**
* <ul>
* <li>file:/c:/filename</li>
* <li>file:/c:/path/filename</li>
* <li>file:/c:/directory1/directory2/filename</li>
* </ul>
*/
file("/((PATH)/(FILENAME))|/(FILENAME)"),
/**
* <ul>
* <li>http://localhost/filename</li>
* <li>http://localhost/path/filename</li>
* <li>http://localhost:8080?id=1234</li>
* </ul>
*/
http("//(HOST)[/|?]((PATH)/(FILENAME))|(FILENAME)|(RESOURCEID)"), ;
// *** static part **************************************************************************************************
private static final Pattern MainUriPattern;
static {
LOGGER.debug("compile main uri regExp: {}", mainUriRegExp());
try {
MainUriPattern = Pattern.compile(mainUriRegExp());
} catch (final PatternSyntaxException pse) {
LOGGER.error("illegal main uri regExp: {}", mainUriRegExp());
throw pse;
}
}
// *** instance part *********************************************************************************************
private final Pattern pattern;
ResourceUriEnum(final String regExp) {
final Map<String, String> WORDS = new HashMap<String, String>();
WORDS.put("PATH", ".+");
WORDS.put("FILENAME", ".+");
WORDS.put("RESOURCEID", ".+");
WORDS.put("HOST", ".+");
String mergeRegExp = regExp;
for (final Entry<String, String> entry : WORDS.entrySet()) {
mergeRegExp = mergeRegExp.replace(entry.getKey(), WORDS.get(entry.getKey()));
}
LOGGER.debug("{} compile local uri regExp: {}", new Object[] { name(), mergeRegExp });
try {
pattern = Pattern.compile(mergeRegExp);
} catch (final PatternSyntaxException pse) {
LOGGER.error("illegal local uri regExp: {}", mergeRegExp);
throw pse;
}
}
/**
* @return local pattern of the binding type
*/
public Pattern getPattern() {
return pattern;
}
/**
* @return main regExp used to identify the type (classpath,file,...) of an uri
*/
private static String mainUriRegExp() {
final StringBuilder str = new StringBuilder();
final ResourceUriEnum[] values = ResourceUriEnum.values();
str.append("(");
for (int i = 0; i < values.length - 1; i++) {
str.append(values[i]).append("|");
}
str.append(values[values.length - 1]);
str.append("):(.*)");
return str.toString();
}
/**
* matcher method
*
* @param uri
* @return bean representation of the uri
*/
public static RegExpSample.ResourceBean match(final String uri) {
if (StringHelper.isEmpty(uri)) { return null; }
final Matcher mainMatcher = MainUriPattern.matcher(uri);
LOGGER.debug("\nmatching uri: {} \nwith regExp: {}", new Object[] { uri, mainUriRegExp() });
if (mainMatcher.find() && mainMatcher.groupCount() >= 2) {
final String strType = mainMatcher.group(1); // extract bindind type
final String localUri = mainMatcher.group(2); // extract the rest of the uri
ResourceBean bean = null;
final ResourceUriEnum type = ResourceUriEnum.valueOf(strType);
final Matcher localMatcher = type.getPattern().matcher(localUri); // create matcher for rest of uri
if (localMatcher.find()) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("matcher group count: {}", localMatcher.groupCount());
for (int i = 0; i <= localMatcher.groupCount(); i++) {
LOGGER.debug("token {} : {}", new Object[] { i, localMatcher.group(i) });
}
if (localMatcher.groupCount() >= 4) {
bean = new ResourceBean();
bean.setType(type);
if (localMatcher.group(4) == null) {
bean.setName(localMatcher.group(3));
bean.setPath(localMatcher.group(2));
} else {
bean.setName(localMatcher.group(4));
bean.setPath(null);
}
} else {
bean = null;
}
}
return bean;
}
return null;
}
return null;
}
}
/**
* POJO representation of a string uri resource which have been match by regexp
*
* @author jraduget
*/
public static class ResourceBean {
private ResourceUriEnum type;
private String name;
private String path;
public ResourceBean() {
}
public ResourceBean(final ResourceUriEnum type, final String path, final String name) {
super();
this.type = type;
this.name = name;
this.path = path;
}
public static ResourceBean parse(final String resourceUri) {
return ResourceUriEnum.match(resourceUri);
}
public ResourceUriEnum getType() {
return type;
}
public void setType(final ResourceUriEnum type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public String getPath() {
return path;
}
public void setPath(final String path) {
this.path = path;
}
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (name == null ? 0 : name.hashCode());
result = prime * result + (path == null ? 0 : path.hashCode());
result = prime * result + (type == null ? 0 : type.hashCode());
return result;
}
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj) {
if (this == obj) { return true; }
if (obj == null) { return false; }
if (!(obj instanceof ResourceBean)) { return false; }
final ResourceBean other = (ResourceBean) obj;
if (name == null) {
if (other.name != null) { return false; }
} else if (!name.equals(other.name)) { return false; }
if (path == null) {
if (other.path != null) { return false; }
} else if (!path.equals(other.path)) { return false; }
if (type == null) {
if (other.type != null) { return false; }
} else if (!type.equals(other.type)) { return false; }
return true;
}
}
// ** test part ****************************************************************************************************
@Test
public void parseIllegal() {
final Map<String, ResourceBean> illegalTests = new LinkedHashMap<String, ResourceBean>();
illegalTests.put("unknown", null);
illegalTests.put("unknown:/", null);
illegalTests.put("unknown://", null);
assertIllegal(illegalTests);
}
@Test
public void parseIllegalClasspath() {
final Map<String, ResourceBean> illegalTests = new LinkedHashMap<String, ResourceBean>();
illegalTests.put("classpath", null);
illegalTests.put("classpath:/", null);
// illegalTests.put("classpath://", null);
assertIllegal(illegalTests);
}
@Test
public void parseLegalClasspath() {
final Map<String, ResourceBean> legalTests = new LinkedHashMap<String, ResourceBean>();
legalTests.put("classpath:/context", new ResourceBean(ResourceUriEnum.classpath, null, "context"));
legalTests.put("classpath:/context.xml", new ResourceBean(ResourceUriEnum.classpath, null, "context.xml"));
legalTests.put("classpath:/localpath1/localpath2/context.xml", new ResourceBean(ResourceUriEnum.classpath, "localpath1/localpath2", "context.xml"));
legalTests.put("classpath:/localpath/context.xml", new ResourceBean(ResourceUriEnum.classpath, "localpath", "context.xml"));
assertLegal(legalTests);
}
@Test
public void parseLegalFile() {
final Map<String, ResourceBean> legalTests = new LinkedHashMap<String, ResourceBean>();
legalTests.put("file:/c:/context", new ResourceBean(ResourceUriEnum.file, "c:", "context"));
legalTests.put("file:/c:/context.xml", new ResourceBean(ResourceUriEnum.file, "c:", "context.xml"));
legalTests.put("file:/c:/localpath1/localpath2/context.xml", new ResourceBean(ResourceUriEnum.file, "c:/localpath1/localpath2", "context.xml"));
legalTests.put("file:/c:/localpath/context.xml", new ResourceBean(ResourceUriEnum.file, "c:/localpath", "context.xml"));
assertLegal(legalTests);
}
/**
* global assertions for legal uri
*
* @param legalTests pair of uri / expected value
*/
void assertLegal(final Map<String, ResourceBean> legalTests) {
for (final Entry<String, ResourceBean> entry : legalTests.entrySet()) {
final ResourceBean bean = ResourceBean.parse(entry.getKey());
assertNotNull("assertion error for: " + entry.getKey(), bean);
assertEquals("assertion error for: " + entry.getKey(), entry.getValue(), bean);
LOGGER.debug(StringHelper.replicate("*", 120));
}
}
/**
* global assertions for illegal uri
*
* @param illegalTests pair of uri / expected value
*/
void assertIllegal(final Map<String, ResourceBean> illegalTests) {
for (final Entry<String, ResourceBean> entry : illegalTests.entrySet()) {
final ResourceBean bean = ResourceBean.parse(entry.getKey());
if (entry.getValue() == null) {
assertNull("assertion error for: " + entry.getKey(), bean);
} else {
assertEquals("assertion error for: " + entry.getKey(), entry.getValue(), bean);
}
LOGGER.debug(StringHelper.replicate("*", 120));
}
}
/**
*
*/
@Test
public void singleTest() {
assertEquals("file:/_/lulu", "file:/${gg}/lulu".replaceFirst("\\$\\{.+\\}", "_"));
assertEquals("file:/_/lulu/_/", "file:/${gg}/lulu/${hhhh}/".replaceAll("\\$\\{.+\\}", "_"));
}
}