All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.integratedmodelling.engine.modelling.kbox.ModelQueryResult Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (C) 2007, 2015:
 * 
 * - Ferdinando Villa  - integratedmodelling.org - any
 * other authors listed in @author annotations
 *
 * All rights reserved. This file is part of the k.LAB software suite, meant to enable
 * modular, collaborative, integrated development of interoperable data and model
 * components. For details, see http://integratedmodelling.org.
 * 
 * This program is free software; you can redistribute it and/or modify it under the terms
 * of the Affero General Public License Version 3 or 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 Affero General Public License for more details.
 * 
 * You should have received a copy of the Affero General Public License along with this
 * program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite
 * 330, Boston, MA 02111-1307, USA. The license is also available at:
 * https://www.gnu.org/licenses/agpl.html
 *******************************************************************************/
package org.integratedmodelling.engine.modelling.kbox;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.integratedmodelling.api.configuration.IResourceConfiguration;
import org.integratedmodelling.api.engine.IModelingEngine;
import org.integratedmodelling.api.metadata.IModelMetadata;
import org.integratedmodelling.api.modelling.IModel;
import org.integratedmodelling.api.modelling.IModelObject;
import org.integratedmodelling.api.modelling.INamespace;
import org.integratedmodelling.api.modelling.IObserver;
import org.integratedmodelling.api.modelling.resolution.IModelPrioritizer;
import org.integratedmodelling.api.monitoring.IMonitor;
import org.integratedmodelling.api.network.API;
import org.integratedmodelling.api.network.IComponent;
import org.integratedmodelling.api.network.INetwork;
import org.integratedmodelling.api.network.INode;
import org.integratedmodelling.api.project.IProject;
import org.integratedmodelling.collections.ImmutableList;
import org.integratedmodelling.common.beans.Model;
import org.integratedmodelling.common.beans.requests.ModelQuery;
import org.integratedmodelling.common.beans.responses.ModelQueryResponse;
import org.integratedmodelling.common.client.NodeClient;
import org.integratedmodelling.common.client.RestTemplateHelper;
import org.integratedmodelling.common.configuration.KLAB;
import org.integratedmodelling.common.kim.KIMModel;
import org.integratedmodelling.common.kim.KIMObserver;
import org.integratedmodelling.common.resources.ResourceFactory;
import org.integratedmodelling.common.utils.StringUtils;
import org.integratedmodelling.engine.modelling.resolver.ModelPrioritizer;
import org.integratedmodelling.exceptions.KlabRuntimeException;

/**
 * Result of a query. The get(n) method returns a model in order of insertion; the
 * iterator returns RANKED models. Model retrieval is lazy and the collection only holds a
 * small amount of ranked metadata until a model is wanted. The model retriever should
 * (eventually) be able to integrate models from any server, local or remote, creating the
 * final models based on the server ID in model data.
 * 
 * @author ferdinando.villa
 *
 */
public class ModelQueryResult extends ImmutableList
        implements INetwork.DistributedOperation, List> {

    IModelPrioritizer comparator;
    ArrayList                  modelData = new ArrayList<>();
    boolean                           sorted    = false;
    IMonitor                          monitor;
    ModelQuery                        query;
    RestTemplateHelper                template;

    public class It implements Iterator {

        Iterator _it;

        It() {
            if (!sorted) {
                Collections.sort(modelData, comparator);
                sorted = true;

                if (KLAB.CONFIG.isDebug()) {
                    if (modelData.size() > 0) {
                        monitor.debug("---- SCORES ------");
                        int n = 1;
                        for (Model md : modelData) {
                            monitor.debug(describeRanks(md, 2, n++));
                        }
                        monitor.debug("------------------");
                    } else {
                        monitor.debug("No results");
                    }
                }
            }
            _it = modelData.iterator();
        }

        @Override
        public boolean hasNext() {
            return _it.hasNext();
        }

        @Override
        public IModel next() {
            return getModel(_it.next());
        }

        @Override
        public void remove() {
            throw new KlabRuntimeException("remove() in ObservationQueryResult iterator is unsupported");
        }
    }

    /**
     * This object is optimized for transparent, lazy retrieving and loading of actual
     * models from model metadata. We can call getModelData() if we want the ranked
     * metadata instead. This will require casting the List coming from
     * {@link ModelKbox query} to a ModelQueryResult first.
     * 
     * @return the ranked model metadata, best match first.
     */
    public List getModelData() {
        if (!sorted) {
            Collections.sort(modelData, comparator);
            sorted = true;
        }
        return modelData;
    }

    private IModel getModel(Model md) {

        IModelObject ret = null;

        if (md == null) {
            return null;
        }
        
        if (md.getServerId() != null && KLAB.MMANAGER.findModelObject(md.getName()) == null) {
            // load remote projects if necessary. After the call, the object should be
            // available locally.
            IProject remoteProject = KLAB.PMANAGER.getProject(md.getProjectUrn());
            if (remoteProject == null) {
                INode node = KLAB.ENGINE.getNetwork().getNode(md.getServerId());
                if (node != null) {
                    try {
                        remoteProject = ResourceFactory
                                .getProjectFromURN(node.getUrl(), md.getProjectUrn(), node.getId(), KLAB.WORKSPACE
                                        .getDeployLocation(), ((IModelingEngine) KLAB.ENGINE)
                                                .getUser());
                        if (!(remoteProject instanceof IComponent)) {
                            KLAB.PMANAGER
                                    .loadProject(remoteProject.getId(), KLAB.MFACTORY
                                            .getRootParsingContext());
                        }
                    } catch (Exception e) {
                        throw new KlabRuntimeException(e);
                    }
                } else {
                    throw new KlabRuntimeException("node " + md.getServerId()
                            + " returned from remote query has become inaccessible");
                }
            }
        }

        INamespace ns = KLAB.MMANAGER.getNamespace(md.getNamespaceId());
        if (ns != null) {
            ret = ns.getModelObject(md.getId());
        }
        if (!(ret instanceof IModel)) {
            return null;
        }
        
        if (md.getDereifyingAttribute() != null) {
            IObserver obs = ((KIMModel) ret).getAttributeObserver(md.getDereifyingAttribute());
            if (obs != null) {
                ret = new KIMModel((KIMObserver) obs, (KIMModel) ret, md.getDereifyingAttribute(), monitor);
            } else {
                return null;
            }
        }

        return (IModel) ret;
    }

    public String describeRanks(Model md, int indent, int n) {

        String ret = "";
        String filler = StringUtils.spaces(indent);

        ret += filler + StringUtils.rightPad(n + ".", 4) + md.getName() + " ["
                + (md.getServerId() == null ? "local" : md.getServerId()) + "]\n";
        Map ranks = comparator.getRanks(md);
        for (String s : comparator.listCriteria()) {
            ret += filler + "  " + StringUtils.rightPad(s, 25) + " "
                    + ranks.get(s) + "\n";
        }

        return ret;
    }

    public ModelQueryResult(IModelPrioritizer prioritizer, IMonitor monitor) {
        comparator = prioritizer;
        this.monitor = monitor;
    }

    @Override
    public boolean contains(Object arg0) {
        throw new KlabRuntimeException("contains() in ObservationQueryResult is unsupported");
    }

    @Override
    public IModel get(int arg0) {
        return getModel(modelData.get(arg0));
    }

    @Override
    public Iterator iterator() {
        return new It();
    }

    @Override
    public int size() {
        return modelData.size();
    }

    @Override
    public Object[] toArray() {
        throw new KlabRuntimeException("toArray() in ObservationQueryResult is unsupported");
    }

    @Override
    public  T[] toArray(T[] arg0) {
        throw new KlabRuntimeException("toArray() in ObservationQueryResult is unsupported");
    }

    @Override
    public boolean acceptNode(INode node) {
        return node.provides(IResourceConfiguration.StaticResource.MODEL_QUERY);
    }

    @Override
    public List executeCall(INode node) {

        if (template == null) {
            template = RestTemplateHelper.newTemplate();
        }

        ModelQueryResponse result = template.with(node)
                .post(node.getUrl() + API.QUERY_MODELS + ".json", ((NodeClient) node)
                        .checkVersion(query), ModelQueryResponse.class);
        return result.getModels();
    }

    @Override
    public List merge(Collection> results) {

        for (List result : results) {
            for (Model md : result) {
                if (!modelData.contains(md)) {
                    addModel(md);
                    ((ModelPrioritizer)comparator).registerRanks(md);
                }
            }
        }

        return modelData;
    }

    public void addModel(Model md) {
        modelData.add(md);
        sorted = false;
    }

    public void setQuery(ModelQuery query) {
        this.query = query;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy