/**
* 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.common.lang;
import static java.util.Collections.unmodifiableSet;
import static org.openbel.framework.common.BELUtilities.constrainedHashMap;
import static org.openbel.framework.common.BELUtilities.constrainedHashSet;
import static org.openbel.framework.common.BELUtilities.nulls;
import static org.openbel.framework.common.enums.SemanticStatus.VALID;
import java.util.Map;
import java.util.Set;
import org.openbel.framework.common.enums.SemanticStatus;
/**
* The base class of the immutable BEL function model.
* <p>
* TODO: The function model currently lacks unit tests
* </p>
*/
public abstract class Function {
private final Set<Signature> signatures;
private final String name;
private final String abbreviation;
private final String briefDescription;
private final int hash;
/**
* Creates a function.
*
* @param name Function name
* @param abbr The function's abbreviation; its short notation (may be null)
* @param brfDesc A brief, <b>one-line</b> description of the function
* @param sigs The supported signatures
* @see Signature Refer here for the format of {@code sigs}
*/
protected Function(String name, String abbr, String brfDesc, String... sigs) {
if (nulls(name, brfDesc, sigs) || sigs.length == 0) {
final String me = getClass().getName();
throw new RuntimeException(me + " is not a valid function");
}
this.name = name;
this.abbreviation = abbr;
this.briefDescription = brfDesc;
hash = getClass().getName().hashCode();
signatures = constrainedHashSet(sigs.length);
for (final String signature : sigs) {
final Signature internalsig = new Signature(signature);
signatures.add(internalsig);
}
}
/**
* Returns a read-only version of the function's signature set.
*
* @return Read-only {@link Set set} of {@link Signature signatures}
*/
public Set<Signature> getSignatures() {
return unmodifiableSet(signatures);
}
/**
* Returns the function's name.
*
* @return {@link String}
*/
public String getName() {
return name;
}
/**
* Returns the function's abbreviation.
*
* @return {@link String}, may be null
*/
public String getAbbreviation() {
return abbreviation;
}
/**
* Returns the function's brief description.
*
* @return {@link String}
*/
public String getBriefDescription() {
return briefDescription;
}
/**
* Returns {@code true} if the provided signature is valid for this
* function, {@code false} otherwise.
* <p>
* You can access the semantic status of invalid signatures (those returning
* {@code false} here) via {@link #getStatus(Signature) getStatus}.
* </p>
*
* @param sig {@link Signature}
* @return boolean
* @see #getStatus(Signature)
*/
public boolean validSignature(final Signature sig) {
if (signatures.contains(sig)) return true;
for (final Signature signature : signatures) {
final SemanticStatus status = signature.matches(sig);
if (status == VALID) return true;
}
return false;
}
/**
* Returns a map of {@link Signature signatures} to {@link SemanticStatus
* semantic status}. The provided signature is checked against all
* signatures of this function.
*
* @param sig {@link Signature}
* @return Map of signatures to semantic status
* @see #validSignature(Signature)
*/
public Map<Signature, SemanticStatus> getStatus(final Signature sig) {
final int sigs_size = signatures.size();
Map<Signature, SemanticStatus> ret = constrainedHashMap(sigs_size);
for (final Signature signature : signatures) {
final SemanticStatus status = signature.matches(sig);
if (status == null) continue;
ret.put(signature, status);
}
return ret;
}
/**
* {@inheritDoc}
*/
@Override
public final String toString() {
StringBuilder bldr = new StringBuilder();
bldr.append("Function [\n");
bldr.append("\tname: ");
bldr.append(name);
bldr.append("\n");
bldr.append("\tabbreviation: ");
if (abbreviation != null)
bldr.append(abbreviation);
bldr.append("\n");
bldr.append("\tbrief description: ");
bldr.append(briefDescription);
bldr.append("\n");
bldr.append("\tsignatures:\n");
for (final Signature sig : signatures) {
bldr.append("\t\t");
bldr.append(sig);
bldr.append("\n");
}
bldr.append("]");
return bldr.toString();
}
/**
* {@inheritDoc}
*/
@Override
public final int hashCode() {
return hash;
}
/**
* {@inheritDoc}
*/
@Override
public final boolean equals(Object obj) {
if (obj == null) return false;
return this.getClass().equals(obj.getClass());
}
/**
* Returns {@code true} if the argument {@code count} is valid for this
* function, {@code false} otherwise.
*
* @param count Argument count
* @return boolean
*/
public abstract boolean validArgumentCount(int count);
}