/**
* EasySOA Registry
* Copyright 2012-2013 Open Wide
*
* 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*
* Contact : easysoa-dev@googlegroups.com
*/
package org.easysoa.registry.indicators.rest;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.easysoa.registry.DocumentService;
import org.easysoa.registry.SubprojectServiceImpl;
import org.easysoa.registry.matching.MatchingHelper;
import org.easysoa.registry.types.Endpoint;
import org.easysoa.registry.types.InformationService;
import org.easysoa.registry.types.ServiceImplementation;
import org.easysoa.registry.types.Subproject;
import org.easysoa.registry.utils.NXQLQueryHelper;
import org.easysoa.registry.wsdl.WsdlBlob;
import org.nuxeo.ecm.core.api.Blob;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.DocumentModelList;
import org.nuxeo.runtime.api.Framework;
/**
* Computes various indicators on services & their impls & endpoints
*
* @author mkalam-alami, mdutoo
*
*/
public class ServiceStateProvider extends IndicatorProviderBase {
private static final String SERVICE_DOCTYPE_INDICATOR = DoctypeCountProvider.buildName(InformationService.DOCTYPE);
ServiceStateProvider(String category){
super(category);
}
@Override
public List<String> getRequiredIndicators() {
return Arrays.asList(SERVICE_DOCTYPE_INDICATOR);
}
@Override
public Map<String, IndicatorValue> computeIndicators(CoreSession session, String subprojectId,
Map<String, IndicatorValue> computedIndicators, String visibility) throws Exception {
DocumentService documentService = Framework.getService(DocumentService.class);
String subprojectCriteria = NXQLQueryHelper.buildSubprojectCriteria(session, subprojectId, visibility);
Map<String, IndicatorValue> indicators = new HashMap<String, IndicatorValue>();
DocumentModelList serviceList = documentService.query(session, DocumentService.NXQL_SELECT_FROM
+ InformationService.DOCTYPE + subprojectCriteria, true, false);
// Count indicators - Service-specific
long servicesCount = computedIndicators.get(SERVICE_DOCTYPE_INDICATOR).getCount();
int serviceWithoutActorNb = 0;
int serviceWithoutInterfaceNb = 0;
int serviceWithoutComponentNb = 0;
int serviceWithMockImplementationNb = 0;
int serviceWithTestedImplementationNb = 0;
int serviceWithoutImplementationNb = 0;
int serviceWithImplementationWhithoutEndpointNb = 0;
int serviceWithImplementationWhithoutProductionEndpointNb = 0;
// % of documented services
int serviceWithDocumentation = this.computeServiceIndicators(session, indicators, subprojectCriteria);
// TODO business services sans interface (InformationService) & in PhaseProgress indicator & governanceIndicators page
for (DocumentModel service : serviceList) {
// Specified services
// TODO rather only specified services ?
String servicePhase = SubprojectServiceImpl.parseSubprojectId(
SubprojectServiceImpl.getSubprojectId(service)).getSubprojectName();
if (Subproject.SPECIFICATIONS_SUBPROJECT_NAME.equals(servicePhase)) {
// Find component
String componentId = (String) service.getPropertyValue(InformationService.XPATH_COMPONENT_ID);
//DocumentModel component = null;
if (componentId == null || componentId.isEmpty()) {
//component = session.getDocument(new IdRef(componentId));
serviceWithoutComponentNb++;
}
// Find actor
String providerActorId = (String) service.getPropertyValue(InformationService.XPATH_PROVIDER_ACTOR);
if (providerActorId == null || providerActorId.isEmpty()) {
serviceWithoutActorNb++;
}
}
// Specified and non-specified (technical) services
if (MatchingHelper.isWsdlInfo(service) && MatchingHelper.isRestInfo(service)) {
serviceWithoutInterfaceNb++;
}
// finding (all) its implems (actual or mock) and then their endpoints
List<DocumentModel> serviceImpls = documentService.getImplementationsOfServiceInCriteria(service, subprojectCriteria);
if (serviceImpls.isEmpty()) {
serviceWithoutImplementationNb++;
//serviceWhithoutImplementationIdSet.add(service.getId());
} else {
boolean isAServiceWithImplementationWhithoutEndpoint = true;
boolean isAServiceWithMockImplementation = false;
boolean isAServiceWithTestedImplementation = false;
for (DocumentModel serviceImplModel : serviceImpls) {
ServiceImplementation serviceImpl = serviceImplModel.getAdapter(ServiceImplementation.class);
if (serviceImpl.isMock()) {
isAServiceWithMockImplementation = true;
} else {
Serializable[] tests = (Serializable[]) serviceImplModel.getPropertyValue(ServiceImplementation.XPATH_TESTS);
if (tests.length != 0) {
isAServiceWithTestedImplementation = true;
}
DocumentModel productionEndpoint = documentService.getEndpointOfImplementation(serviceImplModel, Endpoint.ENV_PRODUCTION, subprojectId);
if (productionEndpoint == null) {
serviceWithImplementationWhithoutProductionEndpointNb++; // at most one production endpoint (else should pass through boolean)
}
List<DocumentModel> endpoints = documentService.getEndpointsOfImplementation(serviceImplModel, subprojectId);
if (endpoints != null && !endpoints.isEmpty()) {
isAServiceWithImplementationWhithoutEndpoint = false;
}
}
}
if (isAServiceWithImplementationWhithoutEndpoint) {
serviceWithImplementationWhithoutEndpointNb++;
}
if (isAServiceWithMockImplementation) {
serviceWithMockImplementationNb++;
}
if (isAServiceWithTestedImplementation) {
serviceWithTestedImplementationNb++;
}
}
}
// Indicators results registration
newIndicator(indicators, "serviceWithoutActor", serviceWithoutActorNb, servicesCount);
newIndicator(indicators, "serviceWithoutInterface", serviceWithoutInterfaceNb, servicesCount);
newIndicator(indicators, "serviceWithoutComponent", serviceWithoutComponentNb, servicesCount);
// TODO "main" vs "test" implementation
newIndicator(indicators, "serviceWithoutImplementation", serviceWithoutImplementationNb, servicesCount);
long serviceWithImplementationNb = servicesCount - serviceWithoutImplementationNb;
newIndicator(indicators, "serviceWithImplementation", serviceWithImplementationNb, servicesCount); // for governance completion
newIndicator(indicators, "serviceWithMockImplementation", serviceWithMockImplementationNb, servicesCount); // for governance completion
newIndicator(indicators, "serviceWithTestedImplementation", serviceWithTestedImplementationNb, servicesCount); // for governance completion
// TODO "test", "integration", "staging" ("design", "dev")
newIndicator(indicators, "serviceWithImplementationWhithoutEndpoint", serviceWithImplementationWhithoutEndpointNb, serviceWithImplementationNb);
newIndicator(indicators, "serviceWithImplementationWhithoutProductionEndpoint", serviceWithImplementationWhithoutProductionEndpointNb, serviceWithImplementationNb);
int serviceWhithoutEndpointNb = serviceWithoutImplementationNb + serviceWithImplementationWhithoutEndpointNb;
newIndicator(indicators, "serviceWithoutEndpoint", serviceWhithoutEndpointNb, servicesCount);
long serviceWithEndpointNb = servicesCount - serviceWhithoutEndpointNb;
newIndicator(indicators, "serviceWithEndpoint", serviceWithEndpointNb, servicesCount); // for governance completion
int serviceWhithoutProductionEndpointNb = serviceWithoutImplementationNb + serviceWithImplementationWhithoutProductionEndpointNb;
newIndicator(indicators, "serviceWithoutProductionEndpoint", serviceWhithoutProductionEndpointNb, servicesCount);
long serviceWithProductionEndpointNb = servicesCount - serviceWhithoutProductionEndpointNb;
newIndicator(indicators, "serviceWithProductionEndpoint", serviceWithProductionEndpointNb, servicesCount); // for governance completion
//% de doc seulement sur les services qui en ont / Qualité de doc moyenne en %
//indicateurs documentation : % d'éléments doc'és (pour service, impl ; non test ; LATER pour consumer)
newIndicator(indicators, "serviceWithDocumentation", serviceWithDocumentation, servicesCount);
return indicators;
}
/**
* Compute value for serviceWithDocumentation indicator
* @param session
* @param indicators
* @param subprojectCriteria
* @return
* @throws Exception
*/
private int computeServiceIndicators(CoreSession session, Map<String, IndicatorValue> indicators, String subprojectCriteria) throws Exception {
DocumentService documentService = Framework.getService(DocumentService.class);
int serviceWithDocumentation = 0;
// Get services specified (else logically won't have any specifications doc but rather ex. javadoc)
// TODO LATER allow to "promote" services detected in the source
DocumentModelList serviceModels = documentService.query(session, DocumentService.NXQL_SELECT_FROM
+ InformationService.DOCTYPE + subprojectCriteria
+ DocumentService.NXQL_AND + "ecm:name='" + Subproject.SPECIFICATIONS_SUBPROJECT_NAME + "'", true, false);
for (DocumentModel serviceModel : serviceModels) {
boolean hasDoc = false;
// Check if there is a joined file or child file (except resource file or wsdl file)
WsdlBlob wsdlBlob = new WsdlBlob(serviceModel);
// ??
if(wsdlBlob.getBlob() != null && !wsdlBlob.getBlob().getFilename().endsWith("wsdl")){
hasDoc = true;
}
if(!hasDoc){
Blob fileBlob;
List<?> files = (List<?>) serviceModel.getPropertyValue("files:files");
if (files != null && !files.isEmpty()) {
for (Object fileInfoObject : files) {
Map<?, ?> fileInfoMap = (Map<?, ?>) fileInfoObject;
fileBlob = (Blob) fileInfoMap.get("file");
// TODO : Add a check for resource file
if (!fileBlob.getFilename().endsWith("wsdl")) {
hasDoc = true;
break;
}
}
}
}
// Increase counter
if(hasDoc){
serviceWithDocumentation++;
}
}
return serviceWithDocumentation;
}
}