package org.easysoa.registry.systems; import java.security.InvalidParameterException; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import org.apache.log4j.Logger; import org.easysoa.registry.DocumentService; import org.easysoa.registry.types.IntelligentSystem; import org.easysoa.registry.types.IntelligentSystemTreeRoot; import org.easysoa.registry.types.ids.SoaNodeId; import org.nuxeo.ecm.core.api.CoreSession; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.runtime.api.Framework; import org.nuxeo.runtime.model.ComponentInstance; import org.nuxeo.runtime.model.DefaultComponent; /** * * @author mkalam-alami * */ public class IntelligentSystemTreeComponent extends DefaultComponent implements IntelligentSystemTreeService { public static final String EXTENSION_POINT_CLASSIFIERS = "classifiers"; public static final String EXTENSION_POINT_ISTS = "intelligentSystemTrees"; private static Logger logger = Logger.getLogger(IntelligentSystemTreeComponent.class); private Map<String, Class<? extends IntelligentSystemTreeClassifier>> classifiers = new HashMap<String, Class<? extends IntelligentSystemTreeClassifier>>(); private Map<String, IntelligentSystemTreeClassifier> ists = new HashMap<String, IntelligentSystemTreeClassifier>(); // TODO Store IST information directly on the document models private Map<String, IntelligentSystemTreeDescriptor> istDescriptors = new HashMap<String, IntelligentSystemTreeDescriptor>(); @Override public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) throws Exception { if (EXTENSION_POINT_CLASSIFIERS.equals(extensionPoint)) { IntelligentSystemTreeClassifierDescriptor descriptor = null; try { // Validate descriptor descriptor = (IntelligentSystemTreeClassifierDescriptor) contribution; if (descriptor.name == null || descriptor.name.isEmpty()) { throw new InvalidParameterException("'name' must not be null"); } // Register classifier class (override potiential previous descriptor) Class<? extends IntelligentSystemTreeClassifier> classifierClass = Class.forName(descriptor.className.trim()).asSubclass(IntelligentSystemTreeClassifier.class); classifiers.put(descriptor.name, classifierClass); } catch (Exception e) { String contribName = (descriptor != null) ? "'" + descriptor.name + "'" : ""; logger.error("Failed to register contribution " + contribName + " to '" + EXTENSION_POINT_CLASSIFIERS + "'", e); } } else if (EXTENSION_POINT_ISTS.equals(extensionPoint)) { IntelligentSystemTreeDescriptor descriptor = null; try { // Validate descriptor descriptor = (IntelligentSystemTreeDescriptor) contribution; if (descriptor.getName() == null || descriptor.getName().isEmpty()) { throw new InvalidParameterException("'name' must not be null"); } if (descriptor.getClassifier() == null || descriptor.getClassifier().isEmpty()) { throw new InvalidParameterException("'classifier' must not be null"); } if (!classifiers.containsKey(descriptor.getClassifier())){ throw new InvalidParameterException("Classifier '" + descriptor.getClassifier() + "' does not exist"); } // Register descriptor istDescriptors.put(descriptor.getName(), descriptor); // Initialize and register IST Class<? extends IntelligentSystemTreeClassifier> istClass = classifiers.get(descriptor.getClassifier()); IntelligentSystemTreeClassifier ist = istClass.newInstance(); ist.initialize(descriptor.getParameters()); ists.put(descriptor.getName(), ist); } catch (Exception e) { String contribName = (descriptor != null) ? "'" + descriptor.getName() + "'" : ""; logger.error("Failed to register contribution " + contribName + " to '" + EXTENSION_POINT_CLASSIFIERS + "'", e); } } } public void handleDocumentModel(CoreSession documentManager, DocumentModel model, boolean force) throws Exception { boolean treeChanged = false; // Filter documents from other intelligent trees String parentType = documentManager.getDocument(model.getParentRef()).getType(); if (!force && IntelligentSystem.DOCTYPE.equals(parentType) || IntelligentSystemTreeRoot.DOCTYPE.equals(parentType)) { return; } // Find the document source & proxies DocumentService documentService = Framework.getService(DocumentService.class); SoaNodeId soaNodeId = documentService.createSoaNodeId(model); DocumentModel sourceModel = documentService.findSoaNode(documentManager, soaNodeId); if (sourceModel == null) { // Can't find source document (can happen when the document is not saved yet) return; } // Run the classifiers IntelligentSystemTreeApi intelligentSystemTreeApi = new IntelligentSystemTreeApiProxyImpl(documentManager); for (Entry<String, IntelligentSystemTreeClassifier> istEntry : ists.entrySet()) { IntelligentSystemTreeDescriptor istDescriptor = istDescriptors.get(istEntry.getKey()); // Filter disabled ISTs if (istDescriptor.isEnabled()) { // Run classifier, that returns a string to tell where the model must be sorted String classification = uniformizeClassificationPath(istEntry.getValue().classify(documentManager, model)); // Find eventual presence of model in the IST String treeName = istDescriptor.getClassifier() + ':' + istDescriptor.getName(); // Handling when model is accepted if (classification != null) { // Fetch or create the IST model if (!intelligentSystemTreeApi.intelligentSystemTreeExists(soaNodeId.getSubprojectId(), treeName)) { intelligentSystemTreeApi.createIntelligentSystemTree(soaNodeId.getSubprojectId(), treeName, istDescriptor.getTitle()); treeChanged = true; } // TODO TODOOOOOOOOOOOOOOOOOOO case of non-default ITS !!!!! // Check if the model is at its right place treeChanged = intelligentSystemTreeApi.classifySoaNode(treeName, soaNodeId, classification) || treeChanged; } // Handling when model is rejected else if (intelligentSystemTreeApi.intelligentSystemTreeExists(soaNodeId.getSubprojectId(), treeName)) { treeChanged = intelligentSystemTreeApi.deleteSoaNode(treeName, soaNodeId) || treeChanged; } } } if (treeChanged) { documentManager.save(); } } private String uniformizeClassificationPath(String classification) { // Make path uniform if (classification == null) { return null; } if (classification.length() > 0 && classification.charAt(0) == '/') { classification = classification.substring(1); } if (classification.length() > 0 && classification.charAt(classification.length() - 1) == '/') { classification = classification.substring(0, classification.length() - 1); } return classification; } }