package org.easysoa.registry; import org.apache.log4j.Logger; import org.easysoa.registry.facets.ServiceImplementationDataFacet; import org.easysoa.registry.matching.MatchingHelper; import org.easysoa.registry.matching.MatchingQuery; import org.easysoa.registry.types.Deliverable; import org.easysoa.registry.types.InformationService; import org.easysoa.registry.types.Platform; import org.easysoa.registry.types.ServiceImplementation; import org.easysoa.registry.utils.EmptyDocumentModelList; import org.nuxeo.ecm.core.api.ClientException; import org.nuxeo.ecm.core.api.CoreSession; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.DocumentModelList; import org.nuxeo.ecm.core.api.model.PropertyException; import org.nuxeo.runtime.api.Framework; /** * TODO matching should be attempted / done if at least one exact (portType, endpointUrl) * or provided guide (component, platform (id) of "actual" (??)) info * (and not only portType) * * @author mdutoo, mkalam-alami * */ public class ServiceMatchingServiceImpl implements ServiceMatchingService { private static Logger logger = Logger.getLogger(ServiceMatchingServiceImpl.class); public boolean isServiceImplementationAlreadyMatched(DocumentModel implDocument) throws PropertyException, ClientException { String providedIServId = (String) implDocument.getPropertyValue(ServiceImplementation.XPATH_PROVIDED_INFORMATION_SERVICE); return providedIServId != null && providedIServId.length() != 0; } /* (non-Javadoc) * @see org.easysoa.registry.ServiceMatchingService#findInformationServices(org.nuxeo.ecm.core.api.CoreSession, org.nuxeo.ecm.core.api.DocumentModel, org.nuxeo.ecm.core.api.DocumentModel, boolean) */ public DocumentModelList findInformationServices(CoreSession documentManager, DocumentModel impl, String filterComponentId, boolean skipPlatformMatching, boolean requireAtLeastOneExactCriteria) throws ClientException { // how should work matching in discovery & dashboard for : // endpoint : if has no impl, // find impl : on IS req itf (portType), and whose IS is in provided component if any, // and whose impl platform (criteria) match the endpoint's discovered impl platform (criteria) if any ; // if single matched link to it // (if more than one result, use matching dashboard) // if none, create impl and do as for in ServiceMatchingImpl : 1. and fill component, else 2. and link to platform, else 3. DocumentService documentService = getDocumentService(); boolean anyExactCriteria = false; MatchingQuery query = new MatchingQuery(DocumentService.NXQL_SELECT_FROM + InformationService.DOCTYPE); // Filter by subproject query.addCriteria(SubprojectServiceImpl.buildCriteriaSeenFromSubproject(impl)); // ex. "AXXXSpecifications"; // or in 2 pass & get it from subProject ?? if (impl.hasFacet(ServiceImplementationDataFacet.FACET_SERVICEIMPLEMENTATIONDATA)) { String implIde = (String) impl.getPropertyValue(ServiceImplementation.XPATH_IMPL_IDE); // OPT only set by ex. FraSCatiStudio, TalendStudio, ScarboModeler String implLanguage = (String) impl.getPropertyValue(ServiceImplementation.XPATH_IMPL_LANGUAGE); // "Java"; // TODO from source disco String implBuild = (String) impl.getPropertyValue(ServiceImplementation.XPATH_IMPL_BUILD); // "Maven" (rather "MavenPom" ?), "Ivy" ; who builds it. TODO Q on top-level DevApp / deliverable only ?!? TODO from source disco or deduced from del:nature if possible String implDeliverableNature = (String) impl.getPropertyValue(Deliverable.XPATH_NATURE); // "Maven" ; MavenArtifact ? copied from Deliverable String implDeliverableRepositoryUrl = (String) impl.getPropertyValue(Deliverable.XPATH_REPOSITORY_URL); // "http://maven.nuxeo.org/nexus/content/groups/public" ; acts as id, copied from Deliverable TODO add in source disco String implServiceLanguage = (String) impl.getPropertyValue(ServiceImplementation.XPATH_TECHNOLOGY); // JAXWS, JAXRS if (!skipPlatformMatching) { // TODO rather match platform only if known as "actual" (or linked platform provided ??), rather than ...IfSet query.addConstraintMatchCriteriaIfSet(Platform.XPATH_IDE, implIde); query.addConstraintMatchCriteriaIfSet(Platform.XPATH_LANGUAGE, implLanguage); query.addConstraintMatchCriteriaIfSet(Platform.XPATH_BUILD, implBuild); query.addConstraintMatchCriteriaIfSet(Platform.XPATH_DELIVERABLE_NATURE, implDeliverableNature); query.addConstraintMatchCriteriaIfSet(Platform.XPATH_DELIVERABLE_REPOSITORY_URL, implDeliverableRepositoryUrl); query.addConstraintMatchCriteriaIfSet(Platform.XPATH_SERVICE_LANGUAGE, implServiceLanguage); } } // else find IS for "matchingFirst" IS (see DiscoveryService) // Filter by component filterComponentId = MatchingHelper.appendComponentFilterToQuery(documentManager, query, filterComponentId, impl); anyExactCriteria = anyExactCriteria || filterComponentId != null; if (MatchingHelper.isWsdlInfo(impl)) { // consistency logic //query.addCriteria("ecm:mixinType = '" + InformationService.FACET_WSDLINFO + "'"); // not required unless added dynamically but hard to do in DiscoveryServiceImpl //query.addCriteria(Platform.XPATH_SERVICE_LANGUAGE , Platform.SERVICE_LANGUAGE_JAXWS); // TODO required ? // NO not necessarily JAXWS ! .NET, HTTP mock or no requirement at all would be OK String implPortTypeName = (String) impl.getPropertyValue(ServiceImplementation.XPATH_WSDL_PORTTYPE_NAME); query.addCriteria(InformationService.XPATH_WSDL_PORTTYPE_NAME, implPortTypeName); anyExactCriteria = true; // NB. NB. exact match (else useless because too wide), is set since is WS(DL) } else if (MatchingHelper.isRestInfo(impl)) { //query.addCriteria("ecm:mixinType = '" + InformationService.FACET_RESTINFO + "'"); // not required unless added dynamically but hard to do in DiscoveryServiceImpl //query.addCriteria(Platform.XPATH_SERVICE_LANGUAGE , Platform.SERVICE_LANGUAGE_JAXRS); // TODO required ? // NO not necessarily JAXRS ! .NET, HTTP mock or no requirement at all would be OK String implRestPath = (String) impl.getPropertyValue(ServiceImplementation.XPATH_REST_PATH); //OPT String implRestAccepts = (String) impl.getPropertyValue(ServiceImplementation.XPATH_REST_ACCEPTS); // OPT //OPT String implRestContentType = (String) impl.getPropertyValue(ServiceImplementation.XPATH_REST_CONTENT_TYPE); // OPT query.addCriteria(InformationService.XPATH_REST_PATH, implRestPath); anyExactCriteria = true; // NB. exact match (else useless because too wide), is set (at least to "") since is REST //query.addConstraintMatchCriteria(InformationService.XPATH_REST_ACCEPTS, implRestAccepts); // OPT //query.addConstraintMatchCriteria(InformationService.XPATH_REST_CONTENT_TYPE, implRestContentType); // OPT } if (requireAtLeastOneExactCriteria && !anyExactCriteria) { return EmptyDocumentModelList.INSTANCE; } String infoServiceQuery = query.build(); DocumentModelList foundInfoServices = documentService.query(documentManager, infoServiceQuery, true, false); return foundInfoServices; } /* (non-Javadoc) * @see org.easysoa.registry.ServiceMatchingService#findServiceImplementations(org.nuxeo.ecm.core.api.CoreSession, org.nuxeo.ecm.core.api.DocumentModel) */ public DocumentModelList findImplementationsCompatibleWithService(CoreSession documentManager, DocumentModel informationService) throws ClientException { DocumentService documentService = getDocumentService(); MatchingQuery query = new MatchingQuery("SELECT * FROM " + ServiceImplementation.DOCTYPE); // Filter by subproject query.addCriteria(SubprojectServiceImpl.buildCriteriaSeesSubproject(informationService)); // NB. multivalued prop if (MatchingHelper.isWsdlInfo(informationService)) { // consistency logic //query.addCriteria("ecm:mixinType = '" + InformationService.FACET_WSDLINFO + "'"); // NO should be added dynamically but hard to do in DiscoveryServiceImpl //query.addConstraintMatchCriteriaIfSet(ServiceImplementation.XPATH_TECHNOLOGY , Platform.SERVICE_LANGUAGE_JAXWS); // require to be its "actual" impl ; OPT for other impl platform metas // NO not necessarily JAWS ! .NET, HTTP mock or no requirement at all would be OK String iservPortTypeName = (String) informationService.getPropertyValue(InformationService.XPATH_WSDL_PORTTYPE_NAME); // if JAXWS query.addCriteria(ServiceImplementation.XPATH_WSDL_PORTTYPE_NAME, iservPortTypeName); // NB. exact match (else useless because too wide), is set since is WS(DL) } else if (MatchingHelper.isRestInfo(informationService)) { //query.addCriteria("ecm:mixinType = '" + ServiceImplementation.FACET_RESTINFO + "'"); // NO should be added dynamically but hard to do in DiscoveryServiceImpl //query.addConstraintMatchCriteriaIfSet(ServiceImplementation.XPATH_TECHNOLOGY , Platform.SERVICE_LANGUAGE_JAXRS); // require to be its "actual" impl ; OPT for other impl platform metas // NO not necessarily JARS ! .NET, HTTP mock or no requirement at all would be OK String iservRestPath = (String) informationService.getPropertyValue(InformationService.XPATH_REST_PATH); //OPT String iservRestAccepts = (String) informationService.getPropertyValue(InformationService.XPATH_REST_ACCEPTS); // OPT //OPT String iservRestContentType = (String) informationService.getPropertyValue(InformationService.XPATH_REST_CONTENT_TYPE); // OPT query.addCriteria(ServiceImplementation.XPATH_REST_PATH, iservRestPath); // NB. exact match (else useless because too wide), is set (at least to "") since is REST //query.addConstraintMatchCriteria(ServiceImplementation.XPATH_REST_ACCEPTS, iservRestAccepts); // OPT //query.addConstraintMatchCriteria(ServiceImplementation.XPATH_REST_CONTENT_TYPE, iservRestContentType); // OPT } // NB. IS-focused & partial matching, other platform metas are checked in the following call to findServiceImplementations() // TODO handle the case of impl-endpoint links that are now wrong i.e. SOA validation String serviceImplQuery = query.build(); DocumentModelList foundImpls = documentService.query(documentManager, serviceImplQuery, true, false); return foundImpls; } /* (non-Javadoc) * @see org.easysoa.registry.ServiceMatchingService#findPlatforms(org.nuxeo.ecm.core.api.CoreSession, org.nuxeo.ecm.core.api.DocumentModel) */ public DocumentModelList findPlatforms(CoreSession documentManager, DocumentModel modelWithPlatformFacet) throws ClientException { DocumentService documentService = getDocumentService(); MatchingQuery query = new MatchingQuery("SELECT * FROM " + Platform.DOCTYPE); // TODO subproject ? NO... for (String property : MatchingHelper.implPlatformPropsToMatch ) { query.addConstraintMatchCriteriaIfSet(property, modelWithPlatformFacet.getPropertyValue(property)); } String serviceImplQuery = query.build(); return documentService.query(documentManager, serviceImplQuery, true, false); } /* (non-Javadoc) * @see org.easysoa.registry.ServiceMatchingService#linkInformationService(org.nuxeo.ecm.core.api.CoreSession, org.nuxeo.ecm.core.api.DocumentModel, java.lang.String, boolean) */ public void linkInformationService(CoreSession documentManager, DocumentModel serviceImplModel, String informationServiceUuid, boolean save) throws ClientException { Object previousLinkValue = serviceImplModel.getPropertyValue(ServiceImplementation.XPATH_PROVIDED_INFORMATION_SERVICE); if (informationServiceUuid == null && previousLinkValue != null || informationServiceUuid != null && !informationServiceUuid.equals(previousLinkValue)) { serviceImplModel.setPropertyValue(ServiceImplementation.XPATH_PROVIDED_INFORMATION_SERVICE, informationServiceUuid); if (save) { documentManager.saveDocument(serviceImplModel); documentManager.save(); } } } private DocumentService getDocumentService() throws ClientException { try { return Framework.getService(DocumentService.class); } catch (Exception e) { throw new ClientException("Document service unavailable, aborting"); } } }