/*
* (C) Copyright IBM Corp. 2013
*
* LICENSE: Eclipse Public License v1.0
* http://www.eclipse.org/legal/epl-v10.html
*/
package com.ibm.gaiandb.webservices.parser.extractors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.junit.Assert;
//import org.junit.Test;
import com.ibm.gaiandb.diags.GDBMessages;
import com.ibm.gaiandb.webservices.parser.AttributeDefinition;
import com.ibm.gaiandb.webservices.parser.NonParsableStringException;
import com.ibm.gaiandb.webservices.parser.properties.AttributeComparator;
/**
* <p>
* Properties Parser Element Extractor.
* <p>
* Extract the different elements composing a tag pattern.
*
* @author remi - IBM Hursley
*
*/
public abstract class PPElementExtractor extends Extractor {
// ----------------------------------------------------------------------------------
// ----------------------------------------------------------------------- ATTRIBUTES
// ======================================================================== Protected
// --------------------------------------------------------------------------- Static
// -------------------------------------------------------------------------- Dynamic
// ========================================================================== Private
// --------------------------------------------------------------------------- Static
private static final String REGEX_NAME_EXTRACTOR = "^\"?([a-zA-Z][\\w- ]*)\"?$|(^\\*$)";
private static final String REGEX_ATTRIBUTE_EXTRACTOR = "^\"?([a-zA-Z][\\w- ]*)\"?.[^\"]?(\"([^<\">]+)\")$";//"^([\\w-]+).[^\"]?((\"([^<\">]+)\")|\\?)$";
private static final String REGEX_POSITION_EXTRACTOR = "^\\[([0-9]+)\\]$";
private static final String REGEX_ATTRIBUTE_TO_FIND_EXTACTOR = "^\"?([a-zA-Z][\\w- ]*)\"?=\\?$";
// -------------------------------------------------------------------------- Dynamic
// =========================================================================== Public
// --------------------------------------------------------------------------- Static
// Use PROPRIETARY notice if class contains a main() method, otherwise use
// COPYRIGHT notice.
public static final String COPYRIGHT_NOTICE = "(c) Copyright IBM Corp. 2013";
public static final String ATTRIBUTE_TO_FIND_MARKER = "?";
/** Index of the name extractor in the extractor list. */
public static final int INDEX_NAME_EXTRACTOR = 0;
/** Index of the name position in the extractor list. */
public static final int INDEX_POSITION_EXTRACTOR = 1;
/** Index of the attribute extractor in the extractor list. */
public static final int INDEX_ATTRIBUTE_EXTRACTOR = 2;
/** Index of the attribute-to-find extractor in the extractor list. */
public static final int INDEX_ATTRIBUTE_TO_FIND_EXTRACTOR = 3;
/** List of extractors for parsing the elements of the GenericWS tree routing language. */
public static final PPElementExtractor[] extractors;
static {
extractors = new PPElementExtractor[4];
// Extractor for a name
// ex <tag-name>
// the name is tag-name
extractors[INDEX_NAME_EXTRACTOR] = new PPElementExtractor() {
/**
* Return the parameter element if it can be extracted.
* @param element
* element to extract values from.
* @return element if it can be extracted.
* @throws NonParsableStringException if the value of element
* cannot be extracted.
*/
@Override
public Object extract(String element) throws NonParsableStringException {
if (!canExtract(element)) {
throw new NonParsableStringException(
GDBMessages.DSWRAPPER_GENERICWS_PROPERTY_PARSING_WRONG_ELEMENT_FORMAT,
"The name element given :" + element + ": cannot be extracted as the " +
"name of a tag.");
}
return element.replaceAll("\"", "");
}
@Override
public boolean canExtract(String element) {
return element.matches(REGEX_NAME_EXTRACTOR);
}
@Override
public PPElementType getExtractedType() {
return PPElementType.NAME;
}
};
// Extractor for the position in [ ]
// ex <tagName [2]>
// the position is 1
// ex <tagName [21]> // 1-based
// the position is 20 // 0-based
extractors[INDEX_POSITION_EXTRACTOR] = new PPElementExtractor() {
/**
* Return the parameter element if it can be extracted.
* Can be extracted if it has the format [X] with X an
* integer value.
* @param element
* element to extract values from.
* @return The integer value between brackets.
* @throws NonParsableStringException if the value of element
* cannot be extracted.
*/
@Override
public Object extract(String element) throws NonParsableStringException {
if (!canExtract(element)) {
throw new NonParsableStringException(
GDBMessages.DSWRAPPER_GENERICWS_PROPERTY_PARSING_WRONG_ELEMENT_FORMAT,
"The name element given :" + element + ": cannot be extracted as the " +
"position of a tag.");
}
Pattern p = Pattern.compile(REGEX_POSITION_EXTRACTOR);
Matcher m = p.matcher(element);
if (m.find()) {
String position = m.group(1);
try {
Integer ret = new Integer(position);
// ret = new Integer(ret.intValue() + 1); // read in 1-based, stored in 0-based
return ret;
}
catch (Exception e) {
// do nothing, will return null;
}
}
return null;
}
/**
* Returns true if element matches [X]. With X an integer. False otherwise.
* @param element The String to check.
* @return true if element matches [X]. With X an integer. False otherwise.
*/
@Override
public boolean canExtract(String element) {
return element.matches(REGEX_POSITION_EXTRACTOR);
}
@Override
public PPElementType getExtractedType() {
return PPElementType.POSITION;
}
};
// Extractor for the attributes and comparator and value
// ex <tagName attr="value"> or <tagName2 attr2!="value2">
// or <tagName3 attr3+="value3">...
// the attribute name is 'attr', the comparator '=' and the value is 'value'
// the attribute name is 'attr2', the comparator '!=' and the value is 'value2'
// the attribute name is 'attr3', the comparator '>' and the value is 'value3'
extractors[INDEX_ATTRIBUTE_EXTRACTOR] = new PPElementExtractor() {
/**
* <p>
* Returns a {@link AtributeDefinition} object containing the
* attribute name, the comparator, and the value affected to
* the attribute.
* <p>
* Can be extracted if it has the format attr="value"
* or attr!="value" or attr+="value"...
* @param element
* element to extract values from.
* @return A AtributeDefinition object defined by the element.
* @throws NonParsableStringException if the value of element
* cannot be extracted.
*/
@Override
public Object extract(String element) throws NonParsableStringException {
if (!canExtract(element)) {
throw new NonParsableStringException(
GDBMessages.DSWRAPPER_GENERICWS_PROPERTY_PARSING_WRONG_ELEMENT_FORMAT,
"The name element given :" + element + ": cannot be extracted as the " +
"attribute definition of a tag.");
}
return extractAttributeDefinition(element);
}
@Override
public boolean canExtract(String element) {
for (AttributeComparator comp : AttributeComparator.comparators) {
if (element.matches(getRegexAttributeDeclaration(comp))) {
return true;
}
}
return false;
// return element.matches(REGEX_ATTRIBUTE_EXTRACTOR);
}
@Override
public PPElementType getExtractedType() {
return PPElementType.ATTRIBUTE;
}
};
// Extractor for the attribute to return
// ex <tagName attr="value" attr2=?>
// the attribute to find is "attr2"
extractors[INDEX_ATTRIBUTE_TO_FIND_EXTRACTOR] = new PPElementExtractor() {
@Override
public Object extract(String element) throws NonParsableStringException {
if (!canExtract(element)) {
throw new NonParsableStringException(
GDBMessages.DSWRAPPER_GENERICWS_PROPERTY_PARSING_WRONG_ELEMENT_FORMAT,
"The name element given :" + element + ": cannot be extracted as an " +
"attribute to find of a tag.");
}
Pattern p = Pattern.compile(REGEX_ATTRIBUTE_TO_FIND_EXTACTOR);
Matcher m = p.matcher(element);
if (m.find()) {
String attributeName = m.group(1);
try {
return attributeName;
}
catch (Exception e) {
// do nothing, will return null;
}
}
return null;
}
@Override
public boolean canExtract(String element) {
return element.matches(REGEX_ATTRIBUTE_TO_FIND_EXTACTOR);
}
@Override
public PPElementType getExtractedType() {
return PPElementType.ATTRIBUTE_TO_FIND;
}
};
}
// -------------------------------------------------------------------------- Dynamic
// ----------------------------------------------------------------------------------
// ---------------------------------------------------------------------------- TOOLS
// ----------------------------------------------------------------------------------
// -------------------------------------------------------------------------- METHODS
// ===================================================================== Constructors
// --------------------------------------------------------------------------- Public
// -------------------------------------------------------------------------- Private
// =========================================================================== Public
// --------------------------------------------------------------------------- Static
// -------------------------------------------------------------------------- Dynamic
public abstract PPElementType getExtractedType();
// ======================================================================== Protected
// --------------------------------------------------------------------------- Static
// -------------------------------------------------------------------------- Dynamic
// ========================================================================== Private
// --------------------------------------------------------------------------- Static
// -------------------------------------------------------------------------- Dynamic
/**
* Parses the parameter token into an attribute definition containing the
* name of the attribute, it reference value, and the comparator used for
* the current comparison.
*
* @param token
* The element to parse.
*
* @return AttributeDefinition containing the name of the attribute, the
* value affected to this one, and the comparator defining the correspondence
* between the attribute and its value.
*
* @throws NonParsableStringException if the string given cannot be
* parsed into an object. Pair<String, Pair<AttributeComparator, String>>
*/
private static AttributeDefinition extractAttributeDefinition(String token)
throws NonParsableStringException {
// Gets through all the comparators to know which one is used
for (AttributeComparator comparator : AttributeComparator.comparators) {
String attribute;
String value;
String REGEX = PPElementExtractor.getRegexAttributeDeclaration(comparator);
Pattern p = Pattern.compile(REGEX);
Matcher m = p.matcher(token);
if (m.find()) {
attribute = m.group(2);
value = m.group(3);
// if attribute and value are null, that mans that the regex has matched
// the pattern attribute to find
if (attribute == null && value == null) {
attribute = m.group(5);
value = m.group(6);
if (attribute == null && value == null) {
throw new NonParsableStringException(
GDBMessages.DSWRAPPER_GENERICWS_PROPERTY_PARSING_WRONG_FORMAT_ATTRIBUTE_DEFINITON,
"The format of the attribute declaration " +
token + " is not valid.");
}
}
return new AttributeDefinition(attribute, comparator,value);
// Pair<String, Pair<AttributeComparator, String>>(
// attribute,
// new Pair<AttributeComparator, String>(comparator, value));
}
// else { -- It is not the right comparator -- }
}
// If none of the known comparators is used
throw new NonParsableStringException(
GDBMessages.DSWRAPPER_GENERICWS_PROPERTY_PARSING_WRONG_FORMAT_ATTRIBUTE_DEFINITON,
"The format of the attribute declaration " +
token + " is not valid.");
}
/**
* Generates a regular expression for matching an attribute definition with
* a given comparator.
* @param comp
* The comparator to use in the regular expression generation.
*/
private static String getRegexAttributeDeclaration(AttributeComparator comp) {
return "(^([\\w]+)" + comp.getRegexSymbol() + "\"(.*)\"$)";// +
//"|(^([\\w]+)" + comp.getRegexSymbol() + "(\\?)$)";
}
// ----------------------------------------------------------------------------------
// ---------------------------------------------------------------------------- TESTS
public static void testFormatSpecifierInputStream () {
System.out.println("Test for PPElementExtractors");
// --------------------------------------------------------
// -- position extractor
Assert.assertTrue("'[23]'" + " should match for the position", "[23]".matches(REGEX_POSITION_EXTRACTOR));
Assert.assertFalse("'[a]'" + " should not match for the position", "[a]".matches(REGEX_POSITION_EXTRACTOR));
Assert.assertFalse("'23'" + " should not match for the position", "23".matches(REGEX_POSITION_EXTRACTOR));
// -- name extractor
Assert.assertTrue("'name_is-here'" + " should match for the name", "name_is-here".matches(REGEX_NAME_EXTRACTOR));
Assert.assertTrue("'*'" + " should match for the name", "*".matches(REGEX_NAME_EXTRACTOR));
Assert.assertFalse("'**'" + " should not match for the name", "**".matches(REGEX_NAME_EXTRACTOR));
Assert.assertFalse("'*test'" + " should not match for the name", "*test".matches(REGEX_NAME_EXTRACTOR));
Assert.assertFalse("'2tr'" + " should not match for the name", "2tr".matches(REGEX_NAME_EXTRACTOR));
// -- attribute extractor
Assert.assertTrue("'name=\"is-here\"'" + " should match for the attribute", "name=\"is-here\"".matches(REGEX_ATTRIBUTE_EXTRACTOR));
Assert.assertTrue("'naMe!=\"is-he_re\"'" + " should match for the attribute", "naMe!=\"is-he_re\"".matches(REGEX_ATTRIBUTE_EXTRACTOR));
Assert.assertTrue("'a!=\"is-he_re\"'" + " should match for the attribute", "a!=\"is-he_re\"".matches(REGEX_ATTRIBUTE_EXTRACTOR));
Assert.assertFalse("'name=\"is-here'" + " should not match for the attribute", "name=\"is-here".matches(REGEX_ATTRIBUTE_EXTRACTOR));
Assert.assertFalse("'name=\"\"is-here\"'" + " should not match for the attribute", "name=\"\"is-here\"".matches(REGEX_ATTRIBUTE_EXTRACTOR));
Assert.assertFalse("'name=\"is-h\"ere\"'" + " should not match for the attribute", "name=\"is-h\"ere\"".matches(REGEX_ATTRIBUTE_EXTRACTOR));
Assert.assertFalse("'name=?'" + " should not match for the attribute", "name=?".matches(REGEX_ATTRIBUTE_EXTRACTOR));
// -- attribute-to-find extractor
Assert.assertTrue("'name=?'" + " should match for the attribute to find", "name=?".matches(REGEX_ATTRIBUTE_TO_FIND_EXTACTOR));
Assert.assertTrue("'a=?'" + " should match for the attribute to find", "a=?".matches(REGEX_ATTRIBUTE_TO_FIND_EXTACTOR));
Assert.assertFalse("'name=\"is-here\"'" + " should not match for the attribute to find", "name=\"is-here\"".matches(REGEX_ATTRIBUTE_TO_FIND_EXTACTOR));
// --------------------------------------------------------
// -- name extractor
try {
String toExtract = "myAttribute=\"value\"";
extractors[INDEX_NAME_EXTRACTOR].extract(toExtract);
Assert.fail(toExtract + " shouldn't match the name extractor.");
} catch (NonParsableStringException e) {
// Yay! Gatcha!
}
try {
String toExtract = "*&^%$";
extractors[INDEX_NAME_EXTRACTOR].extract(toExtract);
Assert.fail(toExtract + " shouldn't match the name extractor.");
} catch (NonParsableStringException e) {
// Yay! Gatcha!
}
try {
String toExtract = "24356";
extractors[INDEX_NAME_EXTRACTOR].extract(toExtract);
Assert.fail(toExtract + " shouldn't match the name extractor.");
} catch (NonParsableStringException e) {
// Yay! Gatcha!
}
// -- attribute extractor
try {
String toExtract = "name=\"is-here";
extractors[INDEX_ATTRIBUTE_EXTRACTOR].extract(toExtract);
Assert.fail(toExtract + " shouldn't match the attribute extractor.");
} catch (NonParsableStringException e) {
// Yay! Gatcha!
}
try {
String toExtract = "a=\"is-here\"";
extractors[INDEX_ATTRIBUTE_EXTRACTOR].extract(toExtract);
} catch (NonParsableStringException e) {
Assert.fail("'a=\"is-here\"' shouldn't match the attribute extractor.");
}
try {
String toExtract = "*&^%$";
extractors[INDEX_ATTRIBUTE_EXTRACTOR].extract(toExtract);
Assert.fail(toExtract + " shouldn't match the attribute extractor.");
} catch (NonParsableStringException e) {
// Yay! Gatcha!
}
try {
String toExtract = "name";
extractors[INDEX_ATTRIBUTE_EXTRACTOR].extract(toExtract);
Assert.fail(toExtract + " shouldn't match the attribute extractor.");
} catch (NonParsableStringException e) {
// Yay! Gatcha!
}
try {
String toExtract = "*";
extractors[INDEX_ATTRIBUTE_EXTRACTOR].extract(toExtract);
Assert.fail(toExtract + " shouldn't match the attribute extractor.");
} catch (NonParsableStringException e) {
// Yay! Gatcha!
}
try {
String toExtract = "[1]";
extractors[INDEX_ATTRIBUTE_EXTRACTOR].extract(toExtract);
Assert.fail(toExtract + " shouldn't match the attribute extractor.");
} catch (NonParsableStringException e) {
// Yay! Gatcha!
}
// -- position extractor
try {
String toExtract = "[1]";
extractors[INDEX_POSITION_EXTRACTOR].extract(toExtract);
} catch (NonParsableStringException e) {
Assert.fail("[1] should match the position extractor.");
}
try {
String toExtract = "*&^%$";
extractors[INDEX_POSITION_EXTRACTOR].extract(toExtract);
Assert.fail(toExtract + " shouldn't match the position extractor.");
} catch (NonParsableStringException e) {
// Yay! Gatcha!
}
try {
String toExtract = "[a]";
extractors[INDEX_POSITION_EXTRACTOR].extract(toExtract);
Assert.fail(toExtract + " shouldn't match the position extractor.");
} catch (NonParsableStringException e) {
// Yay! Gatcha!
}
try {
String toExtract = "name";
extractors[INDEX_POSITION_EXTRACTOR].extract(toExtract);
Assert.fail(toExtract + " shouldn't match the position extractor.");
} catch (NonParsableStringException e) {
// Yay! Gatcha!
}
try {
String toExtract = "attr=\"val\"";
extractors[INDEX_POSITION_EXTRACTOR].extract(toExtract);
Assert.fail(toExtract + " shouldn't match the position extractor.");
} catch (NonParsableStringException e) {
// Yay! Gatcha!
}
try {
String toExtract = "att=?";
extractors[INDEX_POSITION_EXTRACTOR].extract(toExtract);
Assert.fail(toExtract + " shouldn't match the position extractor.");
} catch (NonParsableStringException e) {
// Yay! Gatcha!
}
// -- attribute-to-find extractor
try {
String toExtract = "att=?";
extractors[INDEX_ATTRIBUTE_TO_FIND_EXTRACTOR].extract(toExtract);
} catch (NonParsableStringException e) {
Assert.fail("'att=?' should match the attribute-to-find extractor.");
}
try {
String toExtract = "a=?";
extractors[INDEX_ATTRIBUTE_TO_FIND_EXTRACTOR].extract(toExtract);
} catch (NonParsableStringException e) {
Assert.fail("'a=?' should match the attribute-to-find extractor.");
}
try {
String toExtract = "*&=%$";
extractors[INDEX_ATTRIBUTE_TO_FIND_EXTRACTOR].extract(toExtract);
Assert.fail(toExtract + " shouldn't match the attribute-to-find extractor.");
} catch (NonParsableStringException e) {
// Yay! Gatcha!
}
try {
String toExtract = "name";
extractors[INDEX_ATTRIBUTE_TO_FIND_EXTRACTOR].extract(toExtract);
Assert.fail(toExtract + " shouldn't match the attribute-to-find extractor.");
} catch (NonParsableStringException e) {
// Yay! Gatcha!
}
try {
String toExtract = "attr=\"val\"";
extractors[INDEX_ATTRIBUTE_TO_FIND_EXTRACTOR].extract(toExtract);
Assert.fail(toExtract + " shouldn't match the attribute-to-find extractor.");
} catch (NonParsableStringException e) {
// Yay! Gatcha!
}
try {
String toExtract = "[4]";
extractors[INDEX_ATTRIBUTE_TO_FIND_EXTRACTOR].extract(toExtract);
Assert.fail(toExtract + " shouldn't match the attribute-to-find extractor.");
} catch (NonParsableStringException e) {
// Yay! Gatcha!
}
}
}