/**
* Copyright (C) 2012-2013 Selventa, Inc.
*
* This file is part of the OpenBEL Framework.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The OpenBEL Framework is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the OpenBEL Framework. If not, see <http://www.gnu.org/licenses/>.
*
* Additional Terms under LGPL v3:
*
* This license does not authorize you and you are prohibited from using the
* name, trademarks, service marks, logos or similar indicia of Selventa, Inc.,
* or, in the discretion of other licensors or authors of the program, the
* name, trademarks, service marks, logos or similar indicia of such authors or
* licensors, in any marketing or advertising materials relating to your
* distribution of the program or any covered product. This restriction does
* not waive or limit your obligation to keep intact all copyright notices set
* forth in the program as delivered to you.
*
* If you distribute the program in whole or in part, or any modified version
* of the program, and you assume contractual liability to the recipient with
* respect to the program or modified version, then you will indemnify the
* authors and licensors of the program for any liabilities that these
* contractual assumptions directly impose on those licensors and authors.
*/
package org.openbel.framework.core.compiler;
import static java.lang.System.err;
import static java.util.Arrays.asList;
import static org.junit.Assert.fail;
import static org.openbel.framework.common.model.CommonModelFactory.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.regex.Pattern;
import org.junit.Test;
import org.openbel.framework.common.enums.FunctionEnum;
import org.openbel.framework.common.enums.RelationshipType;
import org.openbel.framework.common.enums.ReturnType;
import org.openbel.framework.common.enums.ValueEncoding;
import org.openbel.framework.common.model.BELObject;
import org.openbel.framework.common.model.Document;
import org.openbel.framework.common.model.Namespace;
import org.openbel.framework.common.model.Parameter;
import org.openbel.framework.common.model.Statement;
import org.openbel.framework.common.model.Term;
import org.openbel.framework.core.compiler.SemanticServiceImpl;
import org.openbel.framework.core.compiler.SemanticWarning;
import org.openbel.framework.core.compiler.SymbolWarning;
import org.openbel.framework.core.indexer.IndexingFailure;
import org.openbel.framework.core.namespace.NamespaceService;
import org.openbel.framework.core.namespace.NamespaceSyntaxWarning;
import org.openbel.framework.core.protocol.ResourceDownloadError;
/**
* Semantic service implementation unit tests.
*/
public class SemanticServiceImplTest {
private static final SemanticServiceImpl subject =
new SemanticServiceImpl(new MockLookupService());
private static final Random random = new Random();
private static FunctionEnum randomFunctionEnum() {
final int count = FunctionEnum.values().length;
return FunctionEnum.values()[random.nextInt(count)];
}
@Test(expected = SemanticWarning.class)
public void testNoArgumentFailure() throws SemanticWarning {
err.println("testNoArgumentFailure");
FunctionEnum funcEnum = FunctionEnum.COMPLEX_ABUNDANCE;
List<BELObject> args = new ArrayList<BELObject>();
Term t = new Term(funcEnum, args);
subject.checkParameterizedTerm(t);
fail("expected semantic failure");
}
@Test(expected = SemanticWarning.class)
public void testMissingFunctionArgumentFailure() throws SemanticWarning {
err.println("testMissingFunctionArgumentFailure");
FunctionEnum funcEnum = FunctionEnum.REACTION;
Term t = new Term(funcEnum);
subject.checkTerm(t);
fail("expected semantic failure");
}
@Test
public void testFunctionOnlyArguments() {
err.println("testFunctionOnlyArguments");
FunctionEnum funcEnum = FunctionEnum.REACTION;
List<BELObject> args = new ArrayList<BELObject>();
args.add(new Term(FunctionEnum.REACTANTS));
args.add(new Term(FunctionEnum.PRODUCTS));
Term t = new Term(funcEnum, args);
try {
subject.checkTerm(t);
} catch (SemanticWarning se) {
fail("unexpected semantic failure: " + se.getUserFacingMessage());
}
}
@Test
public void testEncodingArgument() {
err.println("testEncodingArgument");
FunctionEnum funcEnum = FunctionEnum.ABUNDANCE;
List<BELObject> args = new ArrayList<BELObject>();
Parameter abundance = getInstance().createParameter(null, "value");
args.add(abundance);
Term t = new Term(funcEnum, args);
try {
subject.checkParameterizedTerm(t);
} catch (SemanticWarning se) {
fail("unexpected semantic failure: " + se.getUserFacingMessage());
}
}
@Test
public void testFunctionArgument() {
err.println("testFunctionArgument");
FunctionEnum funcEnum = FunctionEnum.CATALYTIC_ACTIVITY;
List<BELObject> args = new ArrayList<BELObject>();
Term complexAbundance = new Term(FunctionEnum.COMPLEX_ABUNDANCE);
args.add(complexAbundance);
Term t = new Term(funcEnum, args);
try {
subject.checkTerm(t);
} catch (SemanticWarning se) {
fail("unexpected semantic failure: " + se.getUserFacingMessage());
}
}
@Test
public void testComplexArgument() {
err.println("testComplexArgument");
FunctionEnum funcEnum = FunctionEnum.COMPLEX_ABUNDANCE;
List<BELObject> args = new ArrayList<BELObject>();
Parameter parameter = getInstance().createParameter(null, "value");
args.add(parameter);
Term t = new Term(funcEnum, args);
try {
subject.checkParameterizedTerm(t);
} catch (SemanticWarning se) {
fail("unexpected semantic failure: " + se.getUserFacingMessage());
}
args.clear();
int abundances = random.nextInt(10) + 1;
for (int i = 0; i < abundances; i++) {
FunctionEnum fe = randomFunctionEnum();
while (fe.getReturnType() != ReturnType.ABUNDANCE) {
fe = randomFunctionEnum();
}
args.add(new Term(fe));
}
t = new Term(funcEnum, args);
try {
subject.checkParameterizedTerm(t);
} catch (SemanticWarning se) {
fail("unexpected semantic failure: " + se.getUserFacingMessage());
}
}
@Test(expected = SemanticWarning.class)
public void testMultipleEncodings() throws SemanticWarning {
err.println("testMultipleEncodings");
FunctionEnum funcEnum = FunctionEnum.COMPLEX_ABUNDANCE;
List<BELObject> args = new ArrayList<BELObject>();
Parameter g1 = getInstance().createParameter(null, "value1");
Parameter g2 = getInstance().createParameter(null, "value2");
args.add(g1);
args.add(g2);
Term t = new Term(funcEnum, args);
subject.checkParameterizedTerm(t);
fail("expected semantic failure");
}
@Test(expected = SemanticWarning.class)
public void testTooManyArgumentsFailure() throws SemanticWarning {
err.println("testTooManyArgumentsFailure");
FunctionEnum funcEnum = FunctionEnum.PHOSPHATASE_ACTIVITY;
List<BELObject> args = new ArrayList<BELObject>();
Parameter abundance1 = getInstance().createParameter(null, "value1");
Parameter abundance2 = getInstance().createParameter(null, "value2");
args.add(abundance1);
args.add(abundance2);
Term t = new Term(funcEnum, args);
subject.checkParameterizedTerm(t);
fail("expected semantic failure");
}
@Test(expected = SemanticWarning.class)
public void testTooFewArgumentsFailure() throws SemanticWarning {
err.println("testTooFewArgumentsFailure");
FunctionEnum funcEnum = FunctionEnum.TRANSLOCATION;
List<BELObject> args = new ArrayList<BELObject>();
Term abundance = new Term(FunctionEnum.COMPOSITE_ABUNDANCE);
args.add(abundance);
args.add(getInstance().createParameter(null, "value1"));
Term t = new Term(funcEnum, args);
subject.checkParameterizedTerm(t);
fail("expected semantic failure");
}
@Test(expected = SemanticWarning.class)
public void testTicket106_1() throws SemanticWarning {
err.println("testTicket106_1");
FunctionEnum funcEnum = FunctionEnum.PROTEIN_ABUNDANCE;
List<BELObject> args = new ArrayList<BELObject>();
Parameter arg1 = getInstance().createParameter(null, "value1");
Term arg2 = new Term(FunctionEnum.SUBSTITUTION);
Term arg3 = new Term(FunctionEnum.SUBSTITUTION);
Term arg4 = new Term(FunctionEnum.SUBSTITUTION);
args.addAll(asList(new BELObject[] { arg1, arg2, arg3, arg4 }));
Term t = new Term(funcEnum, args);
subject.checkParameterizedTerm(t);
fail("expected semantic failure");
}
@Test(expected = SemanticWarning.class)
public void testTicket106_2() throws SemanticWarning {
err.println("testTicket106_2");
FunctionEnum funcEnum = FunctionEnum.COMPLEX_ABUNDANCE;
List<BELObject> args = new ArrayList<BELObject>();
Term arg1 = new Term(FunctionEnum.ABUNDANCE);
Term arg2 = new Term(FunctionEnum.BIOLOGICAL_PROCESS);
args.addAll(asList(new BELObject[] { arg1, arg2 }));
Term t = new Term(funcEnum, args);
subject.checkParameterizedTerm(t);
fail("expected semantic failure");
}
private static List<BELObject> asBelObjs(BELObject... args) {
return Arrays.asList(args);
}
@Test
public void testProperListUsage() {
err.println("testProperListUsage");
// Test that SemanticServiceImpl#checkListUsage() does not fail
// on proper uses of the LIST function type. The examples here
// are taken from docs/xbel/corpus/small_corpus.bel.
final Namespace pfh =
new Namespace(
"PFH",
"http://resource.belframework.org/"
+
"belframework/1.0/namespace/selventa-named-human-protein-families.belns");
final Namespace hgnc =
new Namespace(
"HGNC",
"http://resource.belframework.org/"
+
"belframework/1.0/namespace/hgnc-approved-symbols.belns");
final Namespace nch =
new Namespace(
"NCH",
"http://resource.belframework.org/"
+
"belframework/1.0/namespace/selventa-named-human-complexes.belns");
// Example 1:
// proteinAbundance(PFH:"RAF Family") hasMembers list(
// proteinAbundance(HGNC:ARAF),
// proteinAbundance(HGNC:BRAF),
// proteinAbundance(HGNC:RAF1))
Term subject1 = new Term(FunctionEnum.PROTEIN_ABUNDANCE,
asBelObjs(new Parameter(pfh, "RAF Family")));
Statement.Object object1 =
new Statement.Object(new Term(FunctionEnum.LIST, asBelObjs(
new Term(FunctionEnum.PROTEIN_ABUNDANCE,
asBelObjs(new Parameter(hgnc, "ARAF"))),
new Term(FunctionEnum.PROTEIN_ABUNDANCE,
asBelObjs(new Parameter(hgnc, "BRAF"))),
new Term(FunctionEnum.PROTEIN_ABUNDANCE,
asBelObjs(new Parameter(hgnc, "RAF1")))
)));
Statement s1 =
new Statement(subject1, null, null, object1,
RelationshipType.HAS_MEMBERS);
// Example 2:
// complexAbundance(NCH:"NADPH Oxidase Complex") hasComponents list(
// proteinAbundance(HGNC:NCF1),
// proteinAbundance(HGNC:CYBB))
Term subject2 = new Term(FunctionEnum.COMPLEX_ABUNDANCE,
asBelObjs(new Parameter(nch, "NADPH Oxidase Complex")));
Statement.Object object2 =
new Statement.Object(new Term(FunctionEnum.LIST, asBelObjs(
new Term(FunctionEnum.PROTEIN_ABUNDANCE,
asBelObjs(new Parameter(hgnc, "NCF1"))),
new Term(FunctionEnum.PROTEIN_ABUNDANCE,
asBelObjs(new Parameter(hgnc, "CYBB"))))));
Statement s2 =
new Statement(subject2, null, null, object2,
RelationshipType.HAS_COMPONENTS);
try {
subject.checkListUsage(s1, null);
subject.checkListUsage(s2, null);
} catch (SemanticWarning se) {
fail("unexpected semantic failure: " + se.getUserFacingMessage());
}
}
@Test(expected = SemanticWarning.class)
public void testImproperListUsage() throws SemanticWarning {
err.println("testImproperListUsage");
// Test that SemanticServiceImpl#checkListUsage() fails
// on improper uses of the LIST function type.
final Namespace meshd =
new Namespace("MESHD", "http://resource.belframework.org/" +
"belframework/1.0/namespace/mesh-diseases.belns");
final Namespace go =
new Namespace(
"GO",
"http://resource.belframework.org/"
+
"belframework/1.0/namespace/go-biological-processes-names.belns");
// The example:
// pathology(MESHD:"Atherosclerosis") positiveCorrelation list(
// biologicalProcess(GO:"lipid oxidation"),
// biologicalProcess(GO:"protein oxidation"))
Term stmtSubject = new Term(FunctionEnum.PATHOLOGY,
asBelObjs(new Parameter(meshd, "Atherosclerosis")));
Statement.Object stmtObject =
new Statement.Object(new Term(FunctionEnum.LIST,
asBelObjs(
new Term(FunctionEnum.BIOLOGICAL_PROCESS,
asBelObjs(new Parameter(go,
"lipid oxidation"))),
new Term(FunctionEnum.BIOLOGICAL_PROCESS,
asBelObjs(new Parameter(go,
"protein oxidation"))))));
Statement s = new Statement(stmtSubject, null, null, stmtObject,
RelationshipType.POSITIVE_CORRELATION);
subject.checkListUsage(s, null);
fail("expected semantic failure");
}
private static class MockLookupService implements NamespaceService {
@Override
public boolean isOpen(String resourceLocation) {
return false;
}
// overridden
@Override
public String lookup(Parameter p) {
return ValueEncoding.ALL_VALUE_ENCODINGS;
}
// no-op
@Override
public void compileNamespace(String resourceLocation)
throws ResourceDownloadError, IndexingFailure {
}
@Override
public void verify(Parameter p) throws NamespaceSyntaxWarning {
}
@Override
public void verify(Document d) throws SymbolWarning {
}
@Override
public void verify(Statement s) throws SymbolWarning, IndexingFailure,
ResourceDownloadError {
}
@Override
public Set<String> search(String resourceLocation, Pattern pattern)
throws IndexingFailure, ResourceDownloadError {
// TODO Auto-generated method stub
return null;
}
}
}