/** * 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.utils; import static java.util.Collections.emptyList; import static org.apache.commons.codec.binary.Base64.decodeBase64; import static org.apache.commons.codec.binary.Base64.encodeBase64; import static org.apache.commons.lang.StringUtils.join; import static org.apache.commons.lang.StringUtils.split; import static org.openbel.framework.common.BELUtilities.hasItems; import static org.openbel.framework.common.BELUtilities.noLength; import static org.openbel.framework.common.enums.CitationType.BOOK; import static org.openbel.framework.common.enums.CitationType.JOURNAL; import static org.openbel.framework.common.enums.CitationType.ONLINE_RESOURCE; import static org.openbel.framework.common.enums.CitationType.OTHER; import static org.openbel.framework.common.enums.CitationType.PUBMED; import static org.openbel.framework.ws.model.CitationType.fromValue; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; import org.openbel.framework.api.KamDialect; import org.openbel.framework.api.KamImpl; import org.openbel.framework.api.KAMStore; import org.openbel.framework.api.KAMStoreException; import org.openbel.framework.api.KamStoreObject; import org.openbel.framework.api.internal.KAMCatalogDao; import org.openbel.framework.api.internal.KAMStoreDaoImpl; import org.openbel.framework.api.internal.KAMCatalogDao.KamInfo; import org.openbel.framework.api.internal.KAMStoreDaoImpl.BelDocumentInfo; import org.openbel.framework.api.internal.KAMStoreDaoImpl.KamProtoEdge; import org.openbel.framework.api.internal.KAMStoreDaoImpl.KamProtoNode; import org.openbel.framework.api.internal.KAMStoreDaoImpl.TermParameter; import org.openbel.framework.common.InvalidArgument; import org.openbel.framework.common.enums.FunctionEnum; import org.openbel.framework.common.enums.ReturnType; import org.openbel.framework.common.model.*; import org.openbel.framework.ws.dialect.BELSyntax; import org.openbel.framework.ws.model.*; import org.openbel.framework.ws.model.Annotation; import org.openbel.framework.ws.model.Citation; import org.openbel.framework.ws.model.Namespace; import org.openbel.framework.ws.model.Statement; /** * Provides static converter methods to go from KamStore objects to JAXB * wire-safe objects for return via the SOAP interface TODO Document * * @author julianjray */ public class Converter { public static final String FIELD_SEP = "|"; private static final Charset ASCII = Charset.forName("US-ASCII"); private static final GregorianCalendar calendar = new GregorianCalendar(); private static final ObjectFactory OBJECT_FACTORY = ObjectFactorySingleton .getInstance(); /** * Converts a {@link KamEdge ws kam edge} to a * {@link org.openbel.framework.api.Kam.KamEdge kam edge} * using the {@link org.openbel.framework.api.Kam kam}. * * @param kamEdge the {@link KamEdge ws kam edge} to convert from * @param kam the {@link org.openbel.framework.api.Kam kam} * to find the kam store kam edge * @return the {@link org.openbel.framework.api.Kam.KamEdge * kam edge} to convert to * @throws InvalidIdException Thrown if the kam edge id is invalid */ public static org.openbel.framework.api.Kam.KamEdge convert(KamEdge kamEdge, org.openbel.framework.api.Kam kam) throws InvalidIdException { if (kamEdge == null) { return null; } final KamStoreObjectRef ref = decodeEdge(kamEdge); int edgeId = ref.getKamStoreObjectId(); return kam.findEdge(edgeId); } /** * @param edgeDirectionType * @return */ public static org.openbel.framework.api.EdgeDirectionType convert(EdgeDirectionType edgeDirectionType) { if (null == edgeDirectionType) { return null; } else if (edgeDirectionType == EdgeDirectionType.FORWARD) { return org.openbel.framework.api.EdgeDirectionType.FORWARD; } else if (edgeDirectionType == EdgeDirectionType.REVERSE) { return org.openbel.framework.api.EdgeDirectionType.REVERSE; } else { return org.openbel.framework.api.EdgeDirectionType.BOTH; } } public static org.openbel.framework.api.EdgeFilter convert( final org.openbel.framework.api.Kam kam, final EdgeFilter filter) { if (filter == null) { return null; } org.openbel.framework.api.EdgeFilter kamEdgeFilter; kamEdgeFilter = kam.createEdgeFilter(); final List<RelationshipTypeFilterCriteria> criterion; criterion = filter.getRelationshipCriteria(); for (final RelationshipTypeFilterCriteria criteria : criterion) { kamEdgeFilter.add(convert(criteria)); } return kamEdgeFilter; } public static org.openbel.framework.api.NodeFilter convert( final org.openbel.framework.api.Kam kam, NodeFilter nodeFilter) { if (null != nodeFilter) { final org.openbel.framework.api.NodeFilter kamNodeFilter = kam .createNodeFilter(); // handle function type criteria List<FunctionTypeFilterCriteria> ftCriterion = nodeFilter .getFunctionTypeCriteria(); for (final FunctionTypeFilterCriteria criteria : ftCriterion) { final org.openbel.framework.api.FunctionTypeFilterCriteria kamNodeCriteria = new org.openbel.framework.api.FunctionTypeFilterCriteria(); kamNodeCriteria.setInclude(criteria.isIsInclude()); final List<FunctionType> functionTypes = criteria.getValueSet(); for (final FunctionType functionType : functionTypes) { final org.openbel.framework.common.enums.FunctionEnum kamNodeFunctionType = convert(functionType); kamNodeCriteria.add(kamNodeFunctionType); } kamNodeFilter.add(kamNodeCriteria); } // handle function return type criteria final List<FunctionReturnTypeFilterCriteria> frtCriterion = nodeFilter .getFunctionReturnCriteria(); for (final FunctionReturnTypeFilterCriteria criteria : frtCriterion) { final org.openbel.framework.api.FunctionReturnFilterCriteria kamNodeCriteria = new org.openbel.framework.api.FunctionReturnFilterCriteria(); kamNodeCriteria.setInclude(criteria.isIsInclude()); final List<FunctionReturnType> functionReturnTypes = criteria.getValueSet(); for (final FunctionReturnType functionReturnType : functionReturnTypes) { final ReturnType kamNodeReturnType = convert(functionReturnType); kamNodeCriteria.add(kamNodeReturnType); } kamNodeFilter.add(kamNodeCriteria); } return kamNodeFilter; } return null; } /** * Converts a {@link KamFilter ws KAM filter} into a {@link KAMCatalogDao.KamFilter KAM filter}. * @param wsFilter * @param kamInfo * @return * @throws InvalidIdException */ public static KAMCatalogDao.KamFilter convert(KamFilter wsFilter, KamInfo kamInfo) throws InvalidIdException { if (null != wsFilter) { // create a new one and send it back KAMCatalogDao.KamFilter ret = kamInfo.createKamFilter(); for (AnnotationFilterCriteria ac : wsFilter.getAnnotationCriteria()) { ret.add(convert(ac)); } for (BelDocumentFilterCriteria bc : wsFilter.getDocumentCriteria()) { ret.add(convert(bc)); } for (CitationFilterCriteria cc : wsFilter.getCitationCriteria()) { ret.add(convert(cc)); } for (RelationshipTypeFilterCriteria rc : wsFilter .getRelationshipCriteria()) { ret.add(convert(rc)); } return ret; } return null; } /** * Converts a {@link AnnotationFilterCriteria ws annotation filter criteria} into * an {@link org.openbel.framework.api.AnnotationFilterCriteria * annotation filter criteria}. * @param wsFilterCriteria * @return * @throws InvalidIdException */ public static org.openbel.framework.api.AnnotationFilterCriteria convert(AnnotationFilterCriteria wsFilterCriteria) throws InvalidIdException { org.openbel.framework.api.AnnotationFilterCriteria filterCriteria = new org.openbel.framework.api.AnnotationFilterCriteria( convert(wsFilterCriteria.getAnnotationType())); filterCriteria.setInclude(wsFilterCriteria.isIsInclude()); for (String s : wsFilterCriteria.getValueSet()) { filterCriteria.add(s); } return filterCriteria; } /** * Converts a {@link AnnotationType ws annotation type} to an * {@link KAMStoreDaoImpl.AnnotationType annotation type}. * @param wsAnnotationType * @return * @throws InvalidIdException */ public static KAMStoreDaoImpl.AnnotationType convert( AnnotationType wsAnnotationType) throws InvalidIdException { String wsId = wsAnnotationType.getId(); String wsName = wsAnnotationType.getName(); String wsDescription = wsAnnotationType.getDescription(); String wsUsage = wsAnnotationType.getUsage(); AnnotationDefinitionType wsAdt = wsAnnotationType.getAnnotationDefinitionType(); final int id = KamStoreObjectRef.decode(wsId, KAMStoreDaoImpl.AnnotationType.class) .getKamStoreObjectId(); KAMStoreDaoImpl.AnnotationDefinitionType adt = convert(wsAdt); return new KAMStoreDaoImpl.AnnotationType(id, wsName, wsDescription, wsUsage, adt); } /** * Converts a {@link AnnotationDefinitionType ws annotation definition type} to a * {@link KAMStoreDaoImpl.AnnotationDefinitionType annotation definition type}. * @param wsAdt * @return */ public static KAMStoreDaoImpl.AnnotationDefinitionType convert( AnnotationDefinitionType wsAdt) { switch (wsAdt) { case ENUMERATION: return KAMStoreDaoImpl.AnnotationDefinitionType.ENUMERATION; case REGULAR_EXPRESSION: return KAMStoreDaoImpl.AnnotationDefinitionType.REGULAR_EXPRESSION; case URL: return KAMStoreDaoImpl.AnnotationDefinitionType.URL; } return null; } /** * Converts a {@link CitationFilterCriteria ws citation filter criteria} into a * {@link org.openbel.framework.api.CitationFilterCriteria * citation filter criteria}. * @param wsFilterCriteria * @return * @throws InvalidIdException */ public static org.openbel.framework.api.CitationFilterCriteria convert(CitationFilterCriteria wsFilterCriteria) throws InvalidIdException { org.openbel.framework.api.CitationFilterCriteria objFilterCriteria = new org.openbel.framework.api.CitationFilterCriteria(); objFilterCriteria.setInclude(wsFilterCriteria.isIsInclude()); for (Citation citation : wsFilterCriteria.getValueSet()) { objFilterCriteria.add(convert(citation)); } return objFilterCriteria; } /** * Converts a {@link Citation ws citation} to a {@link KAMStoreDaoImpl.Citation citation}. * * @param wsCitation * @return */ public static KAMStoreDaoImpl.Citation convert(Citation wsCitation) throws InvalidIdException { String wsId = wsCitation.getId(); String wsName = wsCitation.getName(); CitationType wsCitationType = wsCitation.getCitationType(); String wsComment = wsCitation.getComment(); XMLGregorianCalendar wsPublicationDate = wsCitation.getPublicationDate(); List<String> wsAuthors = wsCitation.getAuthors(); Integer id = null; try { id = Integer.parseInt(wsId); } catch (NumberFormatException e) { throw new InvalidIdException(wsId); } List<String> authors = (wsAuthors == null ? new ArrayList<String>() : wsAuthors); Date publicationDate = (wsPublicationDate != null ? wsPublicationDate.toGregorianCalendar().getTime() : null); return new KAMStoreDaoImpl.Citation( wsName, id.toString(), wsComment, publicationDate, authors, convert(wsCitationType)); } /** * @param filterCriteria * @return */ public static org.openbel.framework.api.CitationFilterCriteria convert(NamespaceFilterCriteria filterCriteria) { org.openbel.framework.api.CitationFilterCriteria objFilterCriteria = new org.openbel.framework.api.CitationFilterCriteria(); objFilterCriteria.setInclude(filterCriteria.isIsInclude()); for (@SuppressWarnings("unused") Namespace namespace : filterCriteria.getValueSet()) { // objFilterCriteria.getValues().add(convert(namespace)); } return objFilterCriteria; } /** * @param wsFilterCriteria * @return */ public static org.openbel.framework.api.BelDocumentFilterCriteria convert(BelDocumentFilterCriteria wsFilterCriteria) throws InvalidIdException { org.openbel.framework.api.BelDocumentFilterCriteria objFilterCriteria = new org.openbel.framework.api.BelDocumentFilterCriteria(); objFilterCriteria.setInclude(wsFilterCriteria.isIsInclude()); for (BelDocument belDocument : wsFilterCriteria.getValueSet()) { objFilterCriteria.add(convert(belDocument)); } return objFilterCriteria; } /** * @param wsFilterCriteria * @return */ public static org.openbel.framework.api.RelationshipTypeFilterCriteria convert(RelationshipTypeFilterCriteria wsFilterCriteria) { org.openbel.framework.api.RelationshipTypeFilterCriteria objFilterCriteria = new org.openbel.framework.api.RelationshipTypeFilterCriteria(); objFilterCriteria.setInclude(wsFilterCriteria.isIsInclude()); for (RelationshipType wsRelationshipType : wsFilterCriteria .getValueSet()) { objFilterCriteria.add(convert(wsRelationshipType)); } return objFilterCriteria; } /** * @param objBelTerm * @return */ public static BelTerm convert(KAMStoreDaoImpl.BelTerm objBelTerm, final KamInfo kamInfo) { BelTerm belTerm = OBJECT_FACTORY.createBelTerm(); belTerm.setId(KamStoreObjectRef.encode(kamInfo, objBelTerm)); belTerm.setLabel(objBelTerm.getLabel()); return belTerm; } /** * @param objBelStatement * @return */ public static BelStatement convert(KAMStoreDaoImpl.BelStatement objBelStatement, final KamInfo kamInfo) { BelStatement belStatement = OBJECT_FACTORY.createBelStatement(); belStatement.setDocument(convert(objBelStatement .getBelDocumentInfo(), kamInfo)); belStatement.setId(KamStoreObjectRef.encode(kamInfo, objBelStatement)); if (null != objBelStatement.getObject()) { if (objBelStatement.getObject() instanceof KAMStoreDaoImpl.BelTerm) { belStatement .setObjectTerm(convert( (KAMStoreDaoImpl.BelTerm) objBelStatement .getObject(), kamInfo)); } else if (objBelStatement.getObject() instanceof KAMStoreDaoImpl.BelStatement) { belStatement .setObjectStatement(convert( (KAMStoreDaoImpl.BelStatement) objBelStatement .getObject(), kamInfo)); } } belStatement.setRelationship(convert(objBelStatement .getRelationshipType())); belStatement.setSubjectTerm(convert(objBelStatement.getSubject(), kamInfo)); belStatement.setCitation(convert(objBelStatement.getCitation())); List<KAMStoreDaoImpl.Annotation> objAnnotations = objBelStatement.getAnnotationList(); for (KAMStoreDaoImpl.Annotation objAnnotation : objAnnotations) { belStatement.getAnnotations().add(convert(kamInfo, objAnnotation)); } return belStatement; } /** * @param statement * @return */ public static Statement convert(org.openbel.framework.common.model.Statement statement) { Statement wsStmt = OBJECT_FACTORY.createStatement(); wsStmt.setStatement(statement.toBELShortForm()); AnnotationGroup group = statement.getAnnotationGroup(); if (group != null) { wsStmt.setCitation(convert(group.getCitation())); List<org.openbel.framework.common.model.Annotation> annotations = group.getAnnotations(); if (hasItems(annotations)) { for (org.openbel.framework.common.model.Annotation annotation : annotations) { wsStmt.getAnnotations().add(convert(annotation)); } } } return wsStmt; } public static Citation convert(org.openbel.framework.common.model.Citation citation) { if (citation == null) return null; Citation wsCitation = OBJECT_FACTORY.createCitation(); wsCitation.setId(citation.getReference()); if (citation.getType() != null) { String value = citation.getType().getDisplayValue().toUpperCase().replace(' ', '_'); wsCitation.setCitationType(fromValue(value)); } if (citation.getName() != null) { wsCitation.setName(citation.getName()); } if (citation.getDate() != null) { try { GregorianCalendar calendar = new GregorianCalendar(); calendar.setTime(citation.getDate().getTime()); wsCitation.setPublicationDate(DatatypeFactory.newInstance().newXMLGregorianCalendar(calendar)); } catch (DatatypeConfigurationException e) { // Swallowed } } if (citation.getAuthors() != null) { wsCitation.getAuthors().addAll(citation.getAuthors()); } wsCitation.setComment(citation.getComment()); return wsCitation; } public static Annotation convert(org.openbel.framework.common.model.Annotation annotation) { if (annotation == null) return null; Annotation wsAnnotation = OBJECT_FACTORY.createAnnotation(); AnnotationType wsAnnotationType = OBJECT_FACTORY.createAnnotationType(); AnnotationDefinition def = annotation.getDefinition(); if (def.getId() != null) wsAnnotationType.setName(def.getId()); if (def.getDescription() != null) wsAnnotationType.setDescription(def.getDescription()); if (def.getUsage() != null) wsAnnotationType.setUsage(def.getUsage()); if (def.getType() != null) { AnnotationDefinitionType ad = AnnotationDefinitionType.fromValue(def.getType().toString()); wsAnnotationType.setAnnotationDefinitionType(ad); } wsAnnotation.setAnnotationType(wsAnnotationType); wsAnnotation.setValue(annotation.getValue()); return wsAnnotation; } /** * @param kam * @param objAnnotation * @return */ public static org.openbel.framework.ws.model.Annotation convert( final KamInfo kamInfo, KAMStoreDaoImpl.Annotation objAnnotation) { AnnotationType convertedType = convert( objAnnotation.getAnnotationType(), kamInfo); org.openbel.framework.ws.model.Annotation annotation = new org.openbel.framework.ws.model.Annotation(); annotation.setAnnotationType(convertedType); annotation.setId(KamStoreObjectRef.encode(kamInfo, objAnnotation)); annotation.setValue(objAnnotation.getValue()); return annotation; } public static RelationshipType convert(final org.openbel.framework.common.enums.RelationshipType relationshipTypeEnum) { if (relationshipTypeEnum == null) { return null; } return RelationshipType.fromValue(relationshipTypeEnum.name()); } public static org.openbel.framework.common.enums.RelationshipType convert(final RelationshipType relationshipTypeEnum) { if (relationshipTypeEnum == null || relationshipTypeEnum == RelationshipType.UNKNOWN) { return null; } return org.openbel.framework.common.enums.RelationshipType .valueOf(relationshipTypeEnum.name()); } public static FunctionType convert( final org.openbel.framework.common.enums.FunctionEnum functionEnum) { if (functionEnum == null) { return null; } return FunctionType.fromValue(functionEnum.name()); } public static FunctionEnum convert(final FunctionType functionType) { if (functionType == null) { return null; } return FunctionEnum.valueOf(functionType.name()); } public static FunctionReturnType convert(final ReturnType returnType) { if (returnType == null) { return null; } return FunctionReturnType.fromValue(returnType.name()); } public static ReturnType convert(final FunctionReturnType functionReturnType) { if (functionReturnType == null) { return null; } return ReturnType.valueOf(functionReturnType.name()); } /** * Converts the KamStore kam node to a {@link KamNode ws kam node}. * * @param objKamNode the KamStore kam node to convert, which can be * {@code null} * @return the converted {@link KamNode ws kam node} or {@code null} if the * KamStore kam node was {@code null} */ public static KamNode convert(final KamInfo kamInfo, org.openbel.framework.api.Kam.KamNode objKamNode) { if (objKamNode == null) { return null; } KamNode kamNode = OBJECT_FACTORY.createKamNode(); kamNode.setFunction(convert(objKamNode.getFunctionType())); kamNode.setId(KamStoreObjectRef.encode(kamInfo, objKamNode)); kamNode.setLabel(objKamNode.getLabel()); return kamNode; } /** * Converts the KamStore kam edge to a {@link KamEdge ws kam edge}. * * @param objKamEdge the KamStore kam edge to convert, which can be * {@code null} * @return the converted {@link KamEdge ws kam edge} or {@code null} if the * KamStore kam edge was {@code null} */ public static KamEdge convert(final KamInfo kamInfo, org.openbel.framework.api.Kam.KamEdge objKamEdge) { if (objKamEdge == null) { return null; } KamEdge kamEdge = OBJECT_FACTORY.createKamEdge(); kamEdge.setId(KamStoreObjectRef.encode(kamInfo, objKamEdge)); kamEdge.setRelationship(convert(objKamEdge.getRelationshipType())); kamEdge.setSource(convert(kamInfo, objKamEdge.getSourceNode())); kamEdge.setTarget(convert(kamInfo, objKamEdge.getTargetNode())); return kamEdge; } /** * Converts {@link org.openbel.framework.common.enums.CitationType} to * {@link CitationType}. * * @param objCitationType Citation type * @return {@link CitationType}; may be null */ public static CitationType convert( org.openbel.framework.common.enums.CitationType objCitationType) { if (objCitationType == null) { return null; } switch (objCitationType) { case BOOK: return CitationType.BOOK; case JOURNAL: return CitationType.JOURNAL; case ONLINE_RESOURCE: return CitationType.ONLINE_RESOURCE; case OTHER: return CitationType.OTHER; case PUBMED: return CitationType.PUBMED; default: return null; } } /** * @param objCitation * @return */ public static Citation convert(KAMStoreDaoImpl.Citation objCitation) { Citation citation = OBJECT_FACTORY.createCitation(); citation.setCitationType(convert(objCitation.getCitationType())); citation.setComment(objCitation.getComment()); citation.setId(objCitation.getId()); citation.setName(objCitation.getName()); Date pubdate = objCitation.getPublicationDate(); if (pubdate != null) { try { calendar.setTime(pubdate); citation.setPublicationDate(DatatypeFactory.newInstance() .newXMLGregorianCalendar(calendar)); } catch (DatatypeConfigurationException e) { // Swallowed } } List<String> authors = objCitation.getAuthors(); if (authors != null) { citation.getAuthors().addAll(authors); } return citation; } /** * @param kamInfo * @return */ public static Kam convert(KAMCatalogDao.KamInfo kamInfo) { Kam kam = OBJECT_FACTORY.createKam(); try { kam.setId(KamStoreObjectRef.encode(kamInfo, kamInfo)); kam.setDescription(kamInfo.getKamDbObject().getDescription()); calendar.setTime(kamInfo.getKamDbObject().getLastCompiled()); kam.setLastCompiled(DatatypeFactory.newInstance() .newXMLGregorianCalendar(calendar)); kam.setName(kamInfo.getKamDbObject().getName()); } catch (DatatypeConfigurationException e) { // Swallowed } return kam; } /** * @param objAnnotationType * @return */ public static AnnotationType convert(KAMStoreDaoImpl.AnnotationType objAnnotationType, final KamInfo kamInfo) { AnnotationType annotationType = OBJECT_FACTORY.createAnnotationType(); annotationType.setDescription(objAnnotationType.getDescription()); annotationType.setId(KamStoreObjectRef.encode(kamInfo, objAnnotationType)); annotationType.setName(objAnnotationType.getName()); annotationType.setUsage(objAnnotationType.getUsage()); annotationType.setAnnotationDefinitionType( AnnotationDefinitionType.valueOf(objAnnotationType .getAnnotationDefinitionType().toString()) ); return annotationType; } /** * @param objBelDocument * @return */ public static BelDocument convert(KAMStoreDaoImpl.BelDocumentInfo docinfo, final KamInfo kamInfo) { BelDocument belDocument = OBJECT_FACTORY.createBelDocument(); String authors = docinfo.getAuthors(); if (authors != null) { for (final String author : split(authors, FIELD_SEP)) { belDocument.getAuthors().add(author); } } belDocument.setContactInfo(docinfo.getContactInfo()); belDocument.setCopyright(docinfo.getCopyright()); belDocument.setDescription(docinfo.getDescription()); belDocument.setDisclaimer(docinfo.getDisclaimer()); belDocument.setId(KamStoreObjectRef.encode(kamInfo, docinfo)); belDocument.setLicenseInfo(docinfo.getLicenseInfo()); belDocument.setName(docinfo.getName()); belDocument.setVersion(docinfo.getVersion()); for (KAMStoreDaoImpl.AnnotationType objAnnotationType : docinfo .getAnnotationTypes()) { belDocument.getAnnotationTypes().add( convert(objAnnotationType, kamInfo)); } for (KAMStoreDaoImpl.Namespace namespace : docinfo .getNamespaces()) { belDocument.getNamespaces().add(convert(namespace, kamInfo)); } return belDocument; } public static KAMStoreDaoImpl.BelDocumentInfo convert(BelDocument source) throws InvalidIdException { String id = source.getId(); String name = source.getName(); String description = source.getDescription(); String version = source.getVersion(); String copyright = source.getCopyright(); String disclaimer = source.getDisclaimer(); String contactInfo = source.getContactInfo(); String licenseInfo = source.getLicenseInfo(); List<String> authors = source.getAuthors(); int intId = KamStoreObjectRef.decode(id, KAMStoreDaoImpl.BelDocumentInfo.class) .getKamStoreObjectId(); String authorString = null; if (hasItems(authors)) { authorString = join(authors, FIELD_SEP); } List<KAMStoreDaoImpl.AnnotationType> emptyAnnos = emptyList(); List<KAMStoreDaoImpl.Namespace> emptyNSs = emptyList(); final KAMStoreDaoImpl.BelDocumentInfo ret = new KAMStoreDaoImpl.BelDocumentInfo( intId, name, description, version, copyright, disclaimer, contactInfo, licenseInfo, authorString, emptyAnnos, emptyNSs); return ret; } /** * @param objNamespace * @return */ public static Namespace convert(KAMStoreDaoImpl.Namespace objNamespace, final KamInfo kamInfo) { Namespace namespace = OBJECT_FACTORY.createNamespace(); namespace.setId(KamStoreObjectRef.encode(kamInfo, objNamespace)); namespace.setPrefix(objNamespace.getPrefix()); namespace.setResourceLocation(objNamespace.getResourceLocation()); return namespace; } public static KAMStoreDaoImpl.Namespace convert(final Namespace src, final org.openbel.framework.api.Kam kam, final KAMStore kAMStore) throws InvalidArgument, KAMStoreException { if (src == null || src.getResourceLocation() == null) { return null; } return kAMStore.getNamespace(kam, src.getResourceLocation()); } /** * Convert a common namespace to a WS namespace. WS namespace will not have * its ID populated as it is not a {@link KamStoreObject} * * @param ns * @return */ public static Namespace convert( final org.openbel.framework.common.model.Namespace ns) { Namespace ws = OBJECT_FACTORY.createNamespace(); ws.setPrefix(ns.getPrefix()); ws.setResourceLocation(ns.getResourceLocation()); return ws; } /** * Convert a WS namespace to a common namespace * * @param ns * @return */ public static org.openbel.framework.common.model.Namespace convert( final Namespace ws) { return new org.openbel.framework.common.model.Namespace( ws.getPrefix(), ws.getResourceLocation()); } public static org.openbel.framework.common.enums.CitationType convert( CitationType c) { if (c == null) { return null; } switch (c) { case BOOK: return BOOK; case JOURNAL: return JOURNAL; case ONLINE_RESOURCE: return ONLINE_RESOURCE; case OTHER: return OTHER; case PUBMED: return PUBMED; default: return null; } } public static SimplePath convert( final org.openbel.framework.api.SimplePath simplePath, final KamInfo kamInfo) { final SimplePath wsSimplePath = new SimplePath(); wsSimplePath.setSource(convert(kamInfo, simplePath.getSource())); wsSimplePath.setTarget(convert(kamInfo, simplePath.getTarget())); for (org.openbel.framework.api.Kam.KamEdge kamEdge : simplePath .getEdges()) { wsSimplePath.getEdges().add(convert(kamInfo, kamEdge)); } return wsSimplePath; } public static BELSyntax convert(BelSyntax ws) { switch (ws) { case LONG_FORM: return BELSyntax.LONG_FORM; case SHORT_FORM: return BELSyntax.SHORT_FORM; default: throw new UnsupportedOperationException("Unsupported syntax: " + ws); } } public static KamStoreObjectRef decodeNode(final KamNode kamNode) throws InvalidIdException { return KamStoreObjectRef.decode(kamNode.getId()); } public static KamStoreObjectRef decodeEdge(final KamEdge kamEdge) throws InvalidIdException { return KamStoreObjectRef.decode(kamEdge.getId()); } public static final class KamStoreObjectRef { private final int kamInfoId; private final int kamStoreObjectId; private final Class<? extends KamStoreObject> kamStoreObjectClass; private final String encodedString; private KamStoreObjectRef(final int kamInfoId, final int kamStoreObjectId, final Class<? extends KamStoreObject> kamStoreObjectClass, final String encodedString) { if (kamStoreObjectId < 1) { throw new InvalidArgument("kamStoreObjectId", kamStoreObjectId); } if (kamStoreObjectClass == null) { throw new InvalidArgument("kamStoreObjectClass", kamStoreObjectClass); } this.kamInfoId = kamInfoId; this.kamStoreObjectId = kamStoreObjectId; this.kamStoreObjectClass = kamStoreObjectClass; this.encodedString = encodedString; } public int getKamInfoId() { return kamInfoId; } public int getKamStoreObjectId() { return kamStoreObjectId; } public Class<? extends KamStoreObject> getKamStoreObjectClass() { return kamStoreObjectClass; } public String getEncodedString() { return encodedString; } /** * Encodes the KamInfo and a KamStoreObject instance as a fixed-length, identifying string. * @param kamInfo * @param obj * @return */ public static String encode(final KamInfo kamInfo, final KamStoreObject obj) { if (obj == null) { return null; } final Integer id = obj.getId(); if (id == null) { return null; } byte prefix = KamStoreObjectType.fromClass(obj.getClass()) .getRepresentation(); return encode(kamInfo.getId().intValue(), id.intValue(), prefix); } /** * Decodes a string that was encoded with {@link encode} back to the id of * some KamStoreObject. * @param encoded * @param expectedClass The class of a subclass of KamStoreObject that will be * used to verify the type encoded in the {@code encode()}ed string. If expectedClass * is null then no verification check is performed. * @return * @throws InvalidIdException Thrown if {@code encoded} is {@code null} or empty, or * if there was an error decoding the {@link encode()}ed string. */ public static KamStoreObjectRef decode(String encoded, Class<? extends KamStoreObject> expectedClass) throws InvalidIdException { return decode(encoded, KamStoreObjectType.fromClass(expectedClass)); } /** * Identical to {@link decode} except that * @param encoded * @return * @throws InvalidIdException */ public static KamStoreObjectRef decode(String encoded) throws InvalidIdException { return decode(encoded, (KamStoreObjectType) null); } /* * Private encoding and decoding methods: */ private static String encode(final int kamInfoId, int id, byte prefix) { final byte[] unencoded = new byte[8]; Arrays.fill(unencoded, (byte) 0); ByteBuffer buffer = ByteBuffer.allocate(8).putInt(kamInfoId).putInt(id); buffer.flip(); buffer.get(unencoded); final byte[] encoded = encodeBase64(unencoded); // Because padding is added for the Base64 encoding, the last byte of encoded // is actually encoded padding and is always '='. This is of no use so // truncate that last byte and add the prefix to the beginning of encoded. shiftRight(encoded); encoded[0] = prefix; return new String(encoded, ASCII); } private static KamStoreObjectRef decode(String encodedStr, KamStoreObjectType expected) throws InvalidIdException { try { if (noLength(encodedStr)) { throw new InvalidIdException(); } final byte[] encoded = encodedStr.getBytes(ASCII); if (encoded.length != 12) { throw new InvalidIdException(encodedStr); } // The first byte should contain an ASCII character // representing the type of object whose ID is encoded. final byte prefix = encoded[0]; final KamStoreObjectType represented = KamStoreObjectType.fromRepresentation(prefix); if (represented == null) { throw new InvalidIdException(encodedStr); } else if (expected != null && represented != expected) { throw new InvalidIdException(encodedStr); } // Remove the prefix byte and add back the byte of Base64-encoded padding. shiftLeft(encoded); encoded[11] = (byte) 0x3d; // '=' in ASCII final byte[] decoded = decodeBase64(encoded); if (decoded.length != 8) { throw new InvalidIdException(encodedStr); } ByteBuffer buffer = ByteBuffer.allocate(8).put(decoded); buffer.flip(); final int kamInfoId = buffer.getInt(); final int kamStoreObjId = buffer.getInt(); return new KamStoreObjectRef(kamInfoId, kamStoreObjId, represented.getRepresentedClass(), encodedStr); } catch (IndexOutOfBoundsException e) { throw new InvalidIdException(encodedStr); } } private static void shiftRight(final byte[] bytes) { for (int i = bytes.length - 1; i > 0; --i) { bytes[i] = bytes[i - 1]; } } private static void shiftLeft(final byte[] bytes) { for (int i = 0; i < bytes.length - 1; ++i) { bytes[i] = bytes[i + 1]; } } } private static enum KamStoreObjectType { ANNOTATION('M', KAMStoreDaoImpl.Annotation.class), ANNOTATION_TYPE('A', KAMStoreDaoImpl.AnnotationType.class), BEL_DOCUMENT_INFO('D', BelDocumentInfo.class), BEL_STATEMENT('S', KAMStoreDaoImpl.BelStatement.class), BEL_TERM('T', KAMStoreDaoImpl.BelTerm.class), KAM_EDGE( 'E', org.openbel.framework.api.Kam.KamEdge.class), KAM_NODE( 'N', org.openbel.framework.api.Kam.KamNode.class), KAM_PROTO_EDGE('R', KamProtoEdge.class), KAM_PROTO_NODE('V', KamProtoNode.class), TERM_PARAMETER('P', TermParameter.class), KAM_IMPL('K', KamImpl.class), KAM_INFO('I', KamInfo.class), NAMESPACE('Q', KAMStoreDaoImpl.Namespace.class), KAM_DIALECT('X', KamDialect.class); private static Map<Class<? extends KamStoreObject>, KamStoreObjectType> classesIndex; private static byte[] representations; private static int[] repIndex; static { final CharsetEncoder asciiEncoder = ASCII.newEncoder(); final KamStoreObjectType[] types = values(); final int n = types.length; classesIndex = new HashMap<Class<? extends KamStoreObject>, KamStoreObjectType>( n); representations = new byte[n]; for (int i = 0; i < n; ++i) { final KamStoreObjectType type = types[i]; classesIndex.put(type.clazz, type); type.repByte = representations[i] = Converter.encode(asciiEncoder, type.rep).byteValue(); } repIndex = sortAndCreateIndex(representations); } private final Class<? extends KamStoreObject> clazz; private final char rep; private byte repByte; private KamStoreObjectType(final char rep, final Class<? extends KamStoreObject> clazz) { this.clazz = clazz; this.rep = rep; this.repByte = 0; } public static KamStoreObjectType fromClass( Class<? extends KamStoreObject> clazz) { KamStoreObjectType ret = classesIndex.get(clazz); if (ret == null) { // check interfaces for (Class<?> i : clazz.getInterfaces()) { if (KamStoreObject.class.isAssignableFrom(i)) { ret = classesIndex.get(i); break; } } } if (ret == null) { throw new UnsupportedOperationException(String.format( "Class '%s' does not have a corresponding %s!", clazz.getName(), KamStoreObjectType.class.getSimpleName())); } return ret; } public static KamStoreObjectType fromRepresentation(final byte rep) { int j = Arrays.binarySearch(representations, rep); return (j >= 0 ? values()[repIndex[j]] : null); } public byte getRepresentation() { return repByte; } public Class<? extends KamStoreObject> getRepresentedClass() { return clazz; } private static int[] sortAndCreateIndex(final byte[] bytes) { int n = bytes.length; int[] index = new int[n]; for (int i = 0; i < n; ++i) { index[i] = i; } for (int i = 0; i < n - 1; ++i) { for (int j = i + 1; j < n; ++j) { if (bytes[i] > bytes[j]) { final byte swap = bytes[i]; final int k = index[i]; bytes[i] = bytes[j]; index[i] = index[j]; bytes[j] = swap; index[j] = k; } } } return index; } } private static Byte encode(final CharsetEncoder encoder, final char c) { encoder.reset(); if (!encoder.canEncode(c)) { return null; } encoder.reset(); ByteBuffer buffer = ByteBuffer.allocate(1); CharBuffer charBuffer = CharBuffer.allocate(1).put(c); charBuffer.flip(); CoderResult result = null; result = encoder.encode(charBuffer, buffer, false); if (!result.isUnderflow()) { return null; } result = encoder.encode(charBuffer, buffer, true); if (result.isMalformed() || result.isUnmappable()) { return null; } result = encoder.flush(buffer); if (!result.isUnderflow()) { return null; } buffer.flip(); return buffer.get(0); } }