[MOBY-guts] biomoby commit
Paul Gordon
gordonp at dev.open-bio.org
Fri Apr 16 17:32:33 UTC 2010
gordonp
Fri Apr 16 13:32:33 EDT 2010
Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services
In directory dev.open-bio.org:/tmp/cvs-serv15243/src/main/ca/ucalgary/seahawk/services
Modified Files:
MobyClient.java
Log Message:
Implemented proper logging, account for deferred data objects
moby-live/Java/src/main/ca/ucalgary/seahawk/services MobyClient.java,1.26,1.27
===================================================================
RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java 2010/04/11 01:58:05 1.26
+++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java 2010/04/16 17:32:33 1.27
@@ -1,6 +1,6 @@
package ca.ucalgary.seahawk.services;
-import ca.ucalgary.seahawk.util.SeahawkOptions;
+import ca.ucalgary.seahawk.util.*;
import org.biomoby.client.*;
import org.biomoby.registry.meta.*;
@@ -116,8 +116,8 @@
docBuilder = dbf.newDocumentBuilder();
}
catch(ParserConfigurationException pce){
- System.err.println("Error: Could not find an XML parser, will not be able to use " +
- "MOBY xpath and regex mapper default behaviors: " + pce);
+ logger.log(Level.SEVERE, "Error: Could not find an XML parser, will not be able to use " +
+ "MOBY xpath and regex mapper default behaviors: ", pce);
}
ClassLoader cl = getClass().getClassLoader();
if(cl == null){
@@ -138,8 +138,8 @@
}
if(dataMappingXMLURL == null){
if(rulesResource.length() != 0){ // if not left intentionally blank
- System.err.println("Could not find MOBY data mapping resource '"+
- rulesResource+"'");
+ logger.log(Level.WARNING, "Could not find MOBY data mapping resource '"+
+ rulesResource+"'");
}
}
else{
@@ -147,7 +147,7 @@
addMappingsFromURL(dataMappingXMLURL);
}
catch(Exception e){
- System.err.println("Error loading default data mapping rules ("+dataMappingXMLURL+"):" + e);
+ logger.log(Level.SEVERE, "Error loading default data mapping rules ("+dataMappingXMLURL+")", e);
e.printStackTrace();
}
}
@@ -198,8 +198,8 @@
*/
public void addMappingsFromURL(URL u) throws Exception{
if(docBuilder == null){
- System.err.println("Asked to add data mappings from file, " +
- "but no XML parser is available");
+ logger.log(Level.SEVERE, "Asked to add data mappings from file, " +
+ "but no XML parser is available");
return;
}
@@ -229,13 +229,13 @@
}
if(nsContext.getNamespaceURI(prefix) != null){
- System.err.println("Prefix definition for " + prefix + " already exists, ignoring new definition");
+ logger.log(Level.WARNING, "Prefix definition for " + prefix + " already exists, ignoring new definition");
return;
}
String nsURI = e.getTextContent();
if(nsURI == null || nsURI.length() == 0){
- System.err.println("Prefix definition for " + prefix + " has a blank URI rule, ignoring");
+ logger.log(Level.WARNING, "Prefix definition for " + prefix + " has a blank URI rule, ignoring");
return;
}
nsContext.setPrefix(nsURI, prefix);
@@ -264,7 +264,7 @@
}
if(!RULE_SET_TAG.equals(ruleSet.getLocalName())){
- System.err.println("Skipping unexpected top level tag " + ruleSet.getLocalName());
+ logger.log(Level.WARNING, "Skipping unexpected top level tag " + ruleSet.getLocalName());
continue;
}
@@ -304,18 +304,18 @@
}
else if(isArticleNameRule(ruleMember)){
if(articleNameString != null && articleNameString.length() != 0){
- System.err.println("Skipping unexpected article name definition node, " +
- "a valid article name rule has already been " +
- "created for this ruleset");
+ logger.log(Level.WARNING, "Skipping unexpected article name definition node, " +
+ "a valid article name rule has already been " +
+ "created for this ruleset");
continue;
}
articleNameString = ruleMember.getTextContent();
}
else if(isDataTypeRule(ruleMember)){
if(dataTypeString != null && dataTypeString.length() != 0){
- System.err.println("Skipping unexpected datatype definition node, " +
- "a valid datatype rule has already been " +
- "created for this ruleset");
+ logger.log(Level.WARNING, "Skipping unexpected datatype definition node, " +
+ "a valid datatype rule has already been " +
+ "created for this ruleset");
continue;
}
dataTypeString = getDataType(ruleMember);
@@ -328,15 +328,15 @@
}
// skip any Dublin Core metadata in validation
else if(!MobyPrefixResolver.DUBLIN_CORE_NAMESPACE.equals(ruleMember.getNamespaceURI())){
- System.err.println("Skipping unexpected "+RULE_SET_TAG+
- " child node " + ruleMember.getLocalName());
+ logger.log(Level.WARNING, "Skipping unexpected "+RULE_SET_TAG+
+ " child node " + ruleMember.getLocalName());
continue;
}
}
if(xpathStrings.size() == 0 && regexStrings.size() == 0 && urlRegexStrings.size() == 0){
- System.err.println("Skipping namespace rule that has no xpath " +
- "url_regex or regex specs associated with it");
+ logger.log(Level.WARNING, "Skipping namespace rule that has no xpath " +
+ "url_regex or regex specs associated with it");
// Next ruleset
continue;
}
@@ -344,9 +344,9 @@
// Simple object with just namespace & ID
if(dataTypeString == null || dataTypeString.length() == 0){
if(memberMap.size() != 0){
- System.err.println("Warning: ignoring member rules, since " +
- "no datatype was defined for the ruleset " +
- "(base Object will be created)");
+ logger.log(Level.WARNING, "Warning: ignoring member rules, since " +
+ "no datatype was defined for the ruleset " +
+ "(base Object will be created)");
}
for(int j = 0; j < xpathStrings.size(); j++){
@@ -362,8 +362,8 @@
// Build complex object
else{
if(memberMap.size() == 0){
- System.err.println("Complex datatype (" + dataTypeString + " was defined " +
- " in the ruleset, but no members were defined");
+ logger.log(Level.WARNING, "Complex datatype (" + dataTypeString + " was defined " +
+ " in the ruleset, but no members were defined");
}
for(int j = 0; j < xpathStrings.size(); j++){
@@ -465,7 +465,7 @@
regexStrings.add(str);
}
else{
- System.err.println("Skipping blank regex rule");
+ logger.log(Level.WARNING, "Skipping blank regex rule");
}
return str;
@@ -483,7 +483,7 @@
urlRegexStrings.add(str);
}
else{
- System.err.println("Skipping blank url_regex rule");
+ logger.log(Level.WARNING, "Skipping blank url_regex rule");
}
return str;
@@ -501,7 +501,7 @@
xPathStrings.add(str);
}
else{
- System.err.println("Skipping blank XPath rule");
+ logger.log(Level.WARNING, "Skipping blank XPath rule");
}
return str;
@@ -524,7 +524,7 @@
String memberNameKey = isPrimitiveDataType(dataTypeName) ?
MobyComplexBuilder.PRIMITIVE_VALUE_SENTINEL : memTag.getAttribute(DATATYPE_RULE_ATTR);
if(ruleValue == null || ruleValue.length() == 0){
- System.err.println("Object member " + memberNameKey + " has a blank value rule");
+ logger.log(Level.WARNING, "Object member " + memberNameKey + " has a blank value rule");
}
String memberDataTypeSetting = memTag.getAttribute(DATATYPE_ATTR);
@@ -574,10 +574,10 @@
!memberWhitespaceSetting.equals(WHITESPACE_ATTR_NORMALIZE_VAL) &&
!memberWhitespaceSetting.equals(WHITESPACE_ATTR_STRIP_FLANKING_VAL) &&
!memberWhitespaceSetting.equals(WHITESPACE_ATTR_STRIP_VAL)){
- System.err.println("Object member " + memberNameKey +
- " has an unrecognized value for the " + WHITESPACE_ATTR +
- " attribute (" + memberWhitespaceSetting +
- "), overriding with default of " + WHITESPACE_ATTR_KEEP_VAL);
+ logger.log(Level.WARNING, "Object member " + memberNameKey +
+ " has an unrecognized value for the " + WHITESPACE_ATTR +
+ " attribute (" + memberWhitespaceSetting +
+ "), overriding with default of " + WHITESPACE_ATTR_KEEP_VAL);
memberWhitespaceSetting = WHITESPACE_ATTR_KEEP_VAL;
}
@@ -587,14 +587,14 @@
}
else if(!memberEncodingSetting.equals(ENCODING_ATTR_NONE_VAL) &&
!memberEncodingSetting.equals(ENCODING_ATTR_BASE64_VAL)){
- System.err.println("Object member " + memberNameKey +
- " has an unrecognized value for the " + ENCODING_ATTR +
- " attribute, overriding with default of " + ENCODING_ATTR_NONE_VAL);
+ logger.log(Level.WARNING, "Object member " + memberNameKey +
+ " has an unrecognized value for the " + ENCODING_ATTR +
+ " attribute, overriding with default of " + ENCODING_ATTR_NONE_VAL);
memberWhitespaceSetting = ENCODING_ATTR_NONE_VAL;
}
if(membersMap.containsKey(memberNameKey)){
- System.err.println("Object member " + memberNameKey + " already exists, ignoring new definition");
+ logger.log(Level.WARNING, "Object member " + memberNameKey + " already exists, ignoring new definition");
return;
}
@@ -637,8 +637,8 @@
" cannot have empty children");
}
if(namespaceStrings.containsKey(keyName)){
- System.err.println("Ignoring duplicate namespace value rule for " +
- "namespace '" + keyName + "'");
+ logger.log(Level.WARNING, "Ignoring duplicate namespace value rule for " +
+ "namespace '" + keyName + "'");
continue;
}
if(keyName != null && keyName.length() != 0){
@@ -649,7 +649,7 @@
}
}
else{
- System.err.println("Skipping unexpected "+NAMESPACE_RULE_TAG+" child node " + specName);
+ logger.log(Level.WARNING, "Skipping unexpected "+NAMESPACE_RULE_TAG+" child node " + specName);
continue;
}
}
@@ -716,13 +716,11 @@
}
}
catch(MobyException me){
- System.err.println("Could not build Moby object from match:" + me);
- me.printStackTrace();
+ logger.log(Level.SEVERE, "Could not build Moby object from match", me);
}
}
} catch(Throwable t){ // Principally stack overflows
- System.err.println("Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to text");
- t.printStackTrace(System.err);
+ logger.log(Level.SEVERE, "Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to text", t);
}
}
}
@@ -765,11 +763,11 @@
// have the exact same contents as the same members who are their
// subtypes, as these are superfluous.
- System.err.println("Multiple Moby objects were found in the text data, " +
- "but the request was to return a simple. " +
- "Only the first value in the collection has been returned.");
+ logger.log(Level.WARNING, "Multiple Moby objects were found in the text data, " +
+ "but the request was to return a simple. " +
+ "Only the first value in the collection has been returned.");
for(MobyDataObject result: results){
- System.err.println("Found object: " + result.getDataType().getName());
+ logger.log(Level.WARNING, "Found object: " + result.getDataType().getName());
}
// TODO: should we instead return the one deepest in the hierarchy (or with the most members)?
return results.elementAt(0);
@@ -818,11 +816,11 @@
// have the exact same contents as the same members who are their
// subtypes, as these are superfluous.
- System.err.println("Multiple Moby objects were found in the text data, " +
- "but the request was to return a simple. " +
- "Only the first value in the collection has been returned.");
+ logger.log(Level.WARNING, "Multiple Moby objects were found in the text data, " +
+ "but the request was to return a simple. " +
+ "Only the first value in the collection has been returned.");
for(MobyDataObject result: results){
- System.err.println("Found object: " + result.getDataType().getName());
+ logger.log(Level.WARNING, "Found object: " + result.getDataType().getName());
}
// TODO: should we instead return the one deepest in the hierarchy (or with the most members)?
return results.elementAt(0);
@@ -916,11 +914,11 @@
// have the exact same contents as the same members who are their
// subtypes, as these are superfluous.
- System.err.println("Multiple Moby objects were found in the text data, " +
- "but the request was to return a simple. " +
- "Only the first value in the collection has been returned.");
+ logger.log(Level.WARNING, "Multiple Moby objects were found in the text data, " +
+ "but the request was to return a simple. " +
+ "Only the first value in the collection has been returned.");
for(MobyDataObject result: results){
- System.err.println("Found object: " + result.getDataType().getName());
+ logger.log(Level.WARNING, "Found object: " + result.getDataType().getName());
}
// TODO: should we instead return the one deepest in the hierarchy (or with the most members)?
return results.elementAt(0);
@@ -994,12 +992,11 @@
}
}
catch(MobyException me){
- System.err.println("Could not build Moby object from match:" + me);
- me.printStackTrace();
+ logger.log(Level.SEVERE, "Could not build Moby object from match", me);
}
}
} catch(Throwable t){ // Principally stack overflows
- System.err.println("Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to binary data");
+ logger.log(Level.SEVERE, "Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to binary data", t);
}
}
}
@@ -1050,7 +1047,7 @@
public Map<String,MobyDataObject[]> getMobyObjectsURNMap(CharSequence textData, byte[] bytes){
Map results = new HashMap<String,MobyDataObject[]>();
if(regexMap.isEmpty()){
- System.out.println("The MOBY Client has not been provided any regex->moby data mappings!");
+ logger.log(Level.WARNING, "The MOBY Client has not been provided any regex->moby data mappings!");
return results;
}
@@ -1069,12 +1066,11 @@
}
}
catch(MobyException me){
- System.err.println("Could not build Moby object from match (rule "+urn+"):" + me);
- me.printStackTrace();
+ logger.log(Level.SEVERE, "Could not build Moby object from match (rule "+urn+")", me);
}
}
}catch(Throwable t){ // Principally stack overflows
- System.err.println("Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to text/binary");
+ logger.log(Level.SEVERE, "Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to text/binary", t);
}
if(urn != null && !objectVector.isEmpty()){
results.put(urn, (MobyDataObject[]) objectVector.toArray(new MobyDataObject[objectVector.size()]));
@@ -1086,7 +1082,7 @@
public MobyDataObject[] getMobyObjects(CharSequence textData, byte[] bytes){
if(regexMap.isEmpty()){
- System.out.println("The MOBY Client has not been provided any regex->moby data mappings!");
+ logger.log(Level.WARNING, "The MOBY Client has not been provided any regex->moby data mappings!");
return new MobyDataObject[0];
}
@@ -1109,12 +1105,11 @@
}
}
catch(MobyException me){
- System.err.println("Could not build Moby object from match:" + me);
- me.printStackTrace();
+ logger.log(Level.SEVERE, "Could not build Moby object from match", me);
}
}
}catch(Throwable t){ // Principally stack overflows
- System.err.println("Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to text/binary");
+ logger.log(Level.SEVERE, "Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to text/binary", t);
}
}
@@ -1142,7 +1137,7 @@
public MobyDataObject[] getMobyObjects(URL url, String linkText, MobyDataType targetDataType){
if(urlRegexMap.isEmpty()){
- System.out.println("The MOBY Client has not been provided any url regex->moby data mappings!");
+ logger.log(Level.WARNING, "The MOBY Client has not been provided any url regex->moby data mappings!");
return new MobyDataObject[0];
}
@@ -1171,8 +1166,7 @@
}
}
catch(MobyException me){
- System.err.println("Could not build Moby object from url regex match:" + me);
- me.printStackTrace();
+ logger.log(Level.SEVERE, "Could not build Moby object from url regex match", me);
}
}
}
@@ -1188,7 +1182,7 @@
// No xpaths to check
if(xpathMap.isEmpty()){
- System.out.println("The MOBY Client has not been provided any xpath->moby data mappings!");
+ logger.log(Level.WARNING, "The MOBY Client has not been provided any xpath->moby data mappings!");
return new MobyDataObject[0];
}
@@ -1224,8 +1218,8 @@
}
}catch(XPathExpressionException xpe2){
- System.err.println( "Warning: Cannot access resulting node list "+
- "due to exception in its retrieval: " + xpe2);
+ logger.log(Level.WARNING, "Warning: Cannot access resulting node list "+
+ "due to exception in its retrieval: ", xpe2);
return new Vector<MobyDataObject>();
}
}
@@ -1241,9 +1235,9 @@
}
}
else{ //not a node sequence
- System.out.println("Warning: the XPath expression ("+ xpath +
- ") did not return a node set, cannot select document elements."+
- " The returned object was of type "+ result.getClass().getName() );
+ logger.log(Level.WARNING, "Warning: the XPath expression ("+ xpath +
+ ") did not return a node set, cannot select document elements."+
+ " The returned object was of type "+ result.getClass().getName() );
return new Vector<MobyDataObject>();
}
}
@@ -1253,8 +1247,8 @@
//xpe.printStackTrace();
return new Vector<MobyDataObject>();
}catch(MobyException me){
- System.err.println("Warning: Cannot create objects from select nodes due " +
- " to exception in MOBY logic:" + me);
+ logger.log(Level.WARNING, "Warning: Cannot create objects from select nodes due " +
+ " to exception in MOBY logic:", me);
return new Vector<MobyDataObject>();
}
@@ -1270,7 +1264,7 @@
// No xpaths to check
if(xpathMap.isEmpty()){
- System.out.println("The MOBY Client has not been provided any xpath->moby data mappings!");
+ logger.log(Level.WARNING, "The MOBY Client has not been provided any xpath->moby data mappings!");
return results;
}
@@ -1340,14 +1334,24 @@
}
if(mdos[i] instanceof MobyDataObject){
- mobyDataServiceAssocInstances[i] = new MobyDataObjectSAI((MobyDataObject) mdos[i], mService);
+ if(mdos[i] instanceof MobyDataObjectDeferred){
+ mobyDataServiceAssocInstances[i] = new MobyDataObjectDeferredSAI((MobyDataObjectDeferred) mdos[i], mService);
+ }
+ else{
+ mobyDataServiceAssocInstances[i] = new MobyDataObjectSAI((MobyDataObject) mdos[i], mService);
+ }
}
else if(mdos[i] instanceof MobyDataObjectSet){
- mobyDataServiceAssocInstances[i] = new MobyDataObjectSetSAI((MobyDataObjectSet) mdos[i], mService);
+ if(mdos[i] instanceof MobyDataObjectSetDeferred){
+ mobyDataServiceAssocInstances[i] = new MobyDataObjectSetDeferredSAI((MobyDataObjectSetDeferred) mdos[i], mService);
+ }
+ else{
+ mobyDataServiceAssocInstances[i] = new MobyDataObjectSetSAI((MobyDataObjectSet) mdos[i], mService);
+ }
}
else{
logger.log(Level.WARNING, "MobyClient could not handle service-associating an instance of " + mdos[i].getClass());
- System.err.println("MobyClient could not handle service-associating an instance of " + mdos[i].getClass());
+ //System.err.println("MobyClient could not handle service-associating an instance of " + mdos[i].getClass());
}
}
return mobyDataServiceAssocInstances;
@@ -1363,7 +1367,7 @@
public void addRegexMapping(String regexp, String[] mobyObj, String articleName, String urn){ //mobyObj<--mobyNamespaces
if(mobyObj == null){
- System.err.println("Ignoring empty namespace-only regex rule mappings");
+ logger.log(Level.WARNING, "Ignoring empty namespace-only regex rule mappings");
return;
}
@@ -1377,7 +1381,7 @@
public void addURLRegexMapping(String url_regexp, String[] mobyObj, String articleName, String urn){ //mobyObj<--mobyNamespaces
if(mobyObj == null){
- System.err.println("Ignoring empty namespace-only url regex rule mappings");
+ logger.log(Level.WARNING, "Ignoring empty namespace-only url regex rule mappings");
return;
}
@@ -1466,7 +1470,7 @@
protected void addRegexMapping(String regexp, Map<String,String> nsRules, String articleName, String ruleName, String urn){ //nsRules = Map<String ns, String regex_replacement>
if(nsRules == null || nsRules.size() == 0){
- System.err.println("Ignoring empty namespace-only regex rule mappings");
+ logger.log(Level.WARNING, "Ignoring empty namespace-only regex rule mappings");
return;
}
@@ -1475,7 +1479,7 @@
protected void addURLRegexMapping(String url_regexp, Map<String,String> url_nsRules, String articleName, String urn){ //nsRules = Map<String ns, String regex_replacement>
if(url_nsRules == null || url_nsRules.size() == 0){
- System.err.println("Ignoring empty namespace-only url regex rule mappings");
+ logger.log(Level.WARNING, "Ignoring empty namespace-only url regex rule mappings");
return;
}
@@ -1517,8 +1521,8 @@
if(memberRelationship.getRelationshipType() == Central.iHAS){
String[] rule = membersMap.get(memberRelationship.getName());
if(rule == null){
- System.err.println("Skipping HAS member "+memberRelationship.getName() +
- " without an explicit rule (may be defined by inheritance?)");
+ logger.log(Level.WARNING, "Skipping HAS member "+memberRelationship.getName() +
+ " without an explicit rule (may be defined by inheritance?)");
continue;
}
Pattern pattern = Pattern.compile(newRegexp, Pattern.DOTALL | Pattern.COMMENTS);
@@ -1527,8 +1531,8 @@
if(captured.containsKey(i)){ //autoboxed int
// Already encapsulated the capture group due to another
// HAS member, don't need to add anything
- System.err.println("Skipping processing of capture group "+i+
- ", it's already been processed by another member in this rule");
+ logger.log(Level.WARNING, "Skipping processing of capture group "+i+
+ ", it's already been processed by another member in this rule");
continue;
}
if(rule[0].matches("^.*\\$"+i+"(?=\\D.*|\\z)")){
@@ -1614,9 +1618,7 @@
}
}catch(Exception e){
- System.err.println("Could not create regular expression statement from '" +
- regexp + "': " + e);
- e.printStackTrace();
+ logger.log(Level.SEVERE, "Could not create regular expression statement from '" + regexp + "'", e);
}
}
@@ -1651,15 +1653,15 @@
builderNameMap.put(urn, mcb);
}
}catch(Exception e){
- System.err.println("Could not create URL regular expression statement from '" +
- url_regexp + "': " + e);
+ logger.log(Level.SEVERE, "Could not create URL regular expression statement from '" +
+ url_regexp + "': " + e);
e.printStackTrace();
}
}
public void addXPathMapping(String xpath, String[] mobyObj){ //mobyObj<--mobyNamespaces
if(mobyObj == null){
- System.err.println("Ignoring empty namespace-only regex rule mappings");
+ logger.log(Level.WARNING, "Ignoring empty namespace-only regex rule mappings");
return;
}
@@ -1707,10 +1709,7 @@
}catch(Exception e){
logger.log(Level.WARNING,
"Could not create XPath select statement from '" +
- xpath_exp + "': " + e.getMessage());
- System.err.println("Could not create XPath select statement from '" +
- xpath_exp + "': " + e);
-
+ xpath_exp + "': ", e);
}
}
@@ -1773,8 +1772,8 @@
else if(line.indexOf("\t") == 0){
String[] fields = line.trim().split(",");
if(fields.length != 2){
- System.err.println("Unrecognized line (not 2 comma delimited fields) " +
- "from ValidateService: " + line.trim());
+ logger.log(Level.WARNING, "Unrecognized line (not 2 comma delimited fields) " +
+ "from ValidateService: " + line.trim());
}
else if(fields[1].equals("true")){
// service is okay, don't add to dead map
@@ -1783,8 +1782,8 @@
isDeadMap.put(currentAuthority+":"+fields[0], "dead");
}
else{
- System.err.println("Unrecognized line (second field not 'true' or 'false') " +
- "from ValidateService: " + line.trim());
+ logger.log(Level.WARNING, "Unrecognized line (second field not 'true' or 'false') " +
+ "from ValidateService: " + line.trim());
}
}
}
More information about the MOBY-guts
mailing list