/**
* 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.ws.endpoint;
import static java.lang.String.format;
import static org.openbel.framework.common.BELUtilities.noLength;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import org.openbel.framework.api.EquivalencerException;
import org.openbel.framework.common.index.Index;
import org.openbel.framework.common.index.ResourceLocation;
import org.openbel.framework.core.indexer.IndexingFailure;
import org.openbel.framework.core.namespace.NamespaceService;
import org.openbel.framework.core.protocol.ResourceDownloadError;
import org.openbel.framework.ws.core.MissingRequest;
import org.openbel.framework.ws.core.RequestException;
import org.openbel.framework.ws.model.EquivalenceId;
import org.openbel.framework.ws.model.FindEquivalencesRequest;
import org.openbel.framework.ws.model.FindEquivalencesResponse;
import org.openbel.framework.ws.model.FindNamespaceEquivalenceRequest;
import org.openbel.framework.ws.model.FindNamespaceEquivalenceResponse;
import org.openbel.framework.ws.model.FindNamespaceValuesRequest;
import org.openbel.framework.ws.model.FindNamespaceValuesResponse;
import org.openbel.framework.ws.model.GetAllNamespacesRequest;
import org.openbel.framework.ws.model.GetAllNamespacesResponse;
import org.openbel.framework.ws.model.Namespace;
import org.openbel.framework.ws.model.NamespaceDescriptor;
import org.openbel.framework.ws.model.NamespaceValue;
import org.openbel.framework.ws.model.ObjectFactory;
import org.openbel.framework.ws.service.EquivalencerService;
import org.openbel.framework.ws.service.NamespaceResourceService;
import org.openbel.framework.ws.utils.ObjectFactorySingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
/**
* ResourceEndPoint defines webservice endpoints to expose functionality related
* to BEL resources: namespaces, equivalences, etc.
*
* @author Anthony Bargnesi {@code <abargnesi@selventa.com>}
* @author Steve Ungerer
*/
@Endpoint
public class ResourceEndPoint extends WebServiceEndpoint {
private static final String FIND_NAMESPACE_EQUIVALENCE_REQUEST =
"FindNamespaceEquivalenceRequest";
private static final String FIND_EQUIVALENCES_REQUEST =
"FindEquivalencesRequest";
private static final String FIND_NAMESPACE_VALUES_REQUEST =
"FindNamespaceValuesRequest";
private static final String GET_ALL_NAMESPACES_REQUEST =
"GetAllNamespacesRequest";
private static final ObjectFactory OBJECT_FACTORY = ObjectFactorySingleton
.getInstance();
@Autowired(required = true)
private EquivalencerService equivalencerService;
@Autowired(required = true)
private NamespaceService namespaceService;
@Autowired(required = true)
private Index resourceIndex;
@Autowired(required = true)
private NamespaceResourceService namespaceResourceService;
public ResourceEndPoint() {
super();
}
@PayloadRoot(namespace = NAMESPACE_URI, localPart = FIND_NAMESPACE_EQUIVALENCE_REQUEST)
@ResponsePayload
public
FindNamespaceEquivalenceResponse findNamespaceEquivalence(
@RequestPayload FindNamespaceEquivalenceRequest request)
throws RequestException {
// validate request
if (request == null) {
throw new MissingRequest(FIND_NAMESPACE_EQUIVALENCE_REQUEST);
}
final NamespaceValue sourceNsValue = verifyNamespaceValue(request
.getNamespaceValue());
final Namespace targetNamespace = verifyNamespace(request
.getTargetNamespace());
try {
final NamespaceValue equivalentNsValue = equivalencerService
.findNamespaceEquivalence(sourceNsValue, targetNamespace);
FindNamespaceEquivalenceResponse response =
OBJECT_FACTORY.createFindNamespaceEquivalenceResponse();
response.setNamespaceValue(equivalentNsValue);
return response;
} catch (EquivalencerException e) {
final String fmt = "error equivalencing %s";
final String msg = format(fmt, sourceNsValue.getValue());
throw new RequestException(msg, e);
}
}
@PayloadRoot(namespace = NAMESPACE_URI, localPart = FIND_EQUIVALENCES_REQUEST)
@ResponsePayload
public
FindEquivalencesResponse findEquivalences(
@RequestPayload FindEquivalencesRequest request)
throws RequestException {
// validate request
if (request == null) {
throw new MissingRequest(FIND_EQUIVALENCES_REQUEST);
}
final NamespaceValue sourceNsValue = verifyNamespaceValue(request
.getNamespaceValue());
try {
final List<NamespaceValue> equivalences = equivalencerService
.findEquivalences(sourceNsValue);
FindEquivalencesResponse response =
OBJECT_FACTORY.createFindEquivalencesResponse();
response.getNamespaceValues().addAll(equivalences);
return response;
} catch (EquivalencerException e) {
final String fmt = "error equivalencing %s";
final String msg = format(fmt, sourceNsValue.getValue());
throw new RequestException(msg, e);
}
}
@PayloadRoot(namespace = NAMESPACE_URI, localPart = FIND_NAMESPACE_VALUES_REQUEST)
@ResponsePayload
public
FindNamespaceValuesResponse findNamespaceValues(
@RequestPayload FindNamespaceValuesRequest request)
throws RequestException {
// validate request
if (request == null) {
throw new MissingRequest(FIND_NAMESPACE_VALUES_REQUEST);
}
List<Namespace> namespaces;
if (request.getNamespaces() == null
|| request.getNamespaces().isEmpty()) {
// get all namespaces we know about
namespaces =
new ArrayList<Namespace>(resourceIndex
.getNamespaceResources().size());
for (ResourceLocation rl : resourceIndex.getNamespaceResources()) {
Namespace ns = new Namespace();
ns.setPrefix(""); // empty prefix, doesn't matter, just can't be null
ns.setResourceLocation(rl.getResourceLocation());
namespaces.add(ns);
}
} else {
namespaces = request.getNamespaces();
}
List<Pattern> patterns =
new ArrayList<Pattern>(request.getPatterns().size());
for (String s : request.getPatterns()) {
patterns.add(verifyPattern(s));
}
FindNamespaceValuesResponse response =
OBJECT_FACTORY.createFindNamespaceValuesResponse();
for (Namespace ns : namespaces) {
ns = verifyNamespace(ns);
try {
// get namespace values
List<String> vals = new ArrayList<String>();
for (Pattern p : patterns) {
vals.addAll(
namespaceService.search(ns.getResourceLocation(), p));
}
// get equivalences
List<NamespaceValue> values = new ArrayList<NamespaceValue>();
for (String v : vals) {
NamespaceValue nv = new NamespaceValue();
nv.setNamespace(ns);
nv.setValue(v);
EquivalenceId eq = equivalencerService.getEquivalenceId(nv);
nv.setEquivalence(eq);
values.add(nv);
}
response.getNamespaceValues().addAll(values);
} catch (IndexingFailure ife) {
final String msg = "error searching namespaces";
throw new RequestException(msg, ife);
} catch (ResourceDownloadError rde) {
final String msg = "error searching namespaces";
throw new RequestException(msg, rde);
} catch (EquivalencerException e) {
final String msg = "error equivalencing patterns";
throw new RequestException(msg, e);
}
}
return response;
}
@PayloadRoot(namespace = NAMESPACE_URI, localPart = GET_ALL_NAMESPACES_REQUEST)
@ResponsePayload
public
GetAllNamespacesResponse
getAllNamespaces(
@SuppressWarnings("unused") @RequestPayload GetAllNamespacesRequest request) {
GetAllNamespacesResponse response = OBJECT_FACTORY
.createGetAllNamespacesResponse();
for (NamespaceDescriptor nd : namespaceResourceService
.getAllNamespaceDescriptors()) {
response.getNamespaceDescriptors().add(nd);
}
return response;
}
private NamespaceValue verifyNamespaceValue(final NamespaceValue nsValue)
throws RequestException {
if (nsValue == null) {
final String msg = "missing namespace value";
throw new RequestException(msg);
}
verifyNamespace(nsValue.getNamespace());
if (noLength(nsValue.getValue())) {
final String msg = "missing namespace value";
throw new RequestException(msg);
}
return nsValue;
}
private Namespace verifyNamespace(final Namespace ns)
throws RequestException {
if (ns == null) {
final String msg = "missing namespace";
throw new RequestException(msg);
}
if (ns.getResourceLocation() == null
|| noLength(ns.getResourceLocation())) {
final String msg = "invalid namespace";
throw new RequestException(msg);
}
return ns;
}
private Pattern verifyPattern(final String s) throws RequestException {
try {
return Pattern.compile(s, Pattern.CASE_INSENSITIVE);
} catch (PatternSyntaxException e) {
final String msg = String.format("Invalid pattern: %s", s);
throw new RequestException(msg);
}
}
}