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

org.ogema.resourcemanager.virtual.DefaultVirtualResourceDB Maven / Gradle / Ivy

/**
 * Copyright 2011-2018 Fraunhofer-Gesellschaft zur Förderung der angewandten Wissenschaften e.V.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.ogema.resourcemanager.virtual;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.ogema.core.model.Resource;
import org.ogema.core.resourcemanager.InvalidResourceTypeException;
import org.ogema.core.resourcemanager.ResourceAlreadyExistsException;
import org.ogema.persistence.ResourceDB;
import org.ogema.persistence.impl.mem.DefaultSimpleResourceData;
import org.ogema.persistence.impl.mem.MemoryResourceDB;
import org.ogema.persistence.impl.mem.MemoryTreeElement;
import org.ogema.resourcetree.SimpleResourceData;
import org.ogema.resourcetree.TreeElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author jlapp
 */
public class DefaultVirtualResourceDB implements VirtualResourceDB {

    final ResourceDB realResources;
    final ResourceDB virtualResources;
    final Logger logger = LoggerFactory.getLogger(getClass());
    final Cache topLevelElementCache = 
            CacheBuilder.newBuilder().weakValues().build();
    private final Object transactionLock = new Object();
    // guarded by transactionLock
    private int transactionCounter = 0;
//new ConcurrentHashMap<>();

    private final RemovalListener cacheListener = new RemovalListener() {

        @Override
        public void onRemoval(RemovalNotification notification) {
            logger.trace("element removed from cache ({}): {}", notification.getCause(), notification.getKey());
        }
    };    
    final Cache elements =
            CacheBuilder.newBuilder().weakValues().removalListener(cacheListener).build();//new ConcurrentHashMap<>();

    public DefaultVirtualResourceDB(ResourceDB realResources) {
        this.realResources = realResources;
        this.virtualResources = new MemoryResourceDB();
    }

    @Override
    public VirtualTreeElement addResource(String name, Class type, String appID)
            throws ResourceAlreadyExistsException, InvalidResourceTypeException {
        TreeElement te = realResources.addResource(name, type, appID);
        DefaultVirtualTreeElement dvte = getElement(te);
        // MemoryTreeElement updates
        for (DefaultVirtualTreeElement child : dvte.virtualSubresources.values()) {
        	if (child.isVirtual()) {
        		((MemoryTreeElement) child.getEl()).setParent(dvte.getEl());
        	}
        }
        return dvte;
    }

    @Override
    public VirtualTreeElement getToplevelResource(String name) {
        VirtualTreeElement vte = topLevelElementCache.getIfPresent(name);
        if (vte != null) {
            return vte;
        }
        TreeElement te = realResources.getToplevelResource(name);
        if (te != null) {
            vte = getElement(te);
            topLevelElementCache.put(name, vte);
        }
        return vte;
    }

    @Override
    public Class addOrUpdateResourceType(Class type)
            throws ResourceAlreadyExistsException, InvalidResourceTypeException {
        virtualResources.addOrUpdateResourceType(type);
        return realResources.addOrUpdateResourceType(type);
    }

    @Override
    public Collection> getTypeChildren(String name) throws InvalidResourceTypeException {
        return realResources.getTypeChildren(name);
    }

    @Override
    public boolean hasResourceType(String name) {
        return realResources.hasResourceType(name);
    }

    @Override
    public List> getAllResourceTypesInstalled() {
        return realResources.getAllResourceTypesInstalled();
    }

    @Override
    public void deleteResource(TreeElement elem) {
        makeVirtual(elem);
    }
    

    @SuppressWarnings("deprecation")
    private void makeVirtual(TreeElement elem) {
        final DefaultVirtualTreeElement virtualElement = getElement(elem);
        if (!elem.isReference()) {
            for (TreeElement child : virtualElement.getChildren()) {
                makeVirtual(child);
            }
        }
        
        if (!virtualElement.isVirtual()) {
            TreeElement realElement = virtualElement.getEl();
            TreeElement realParent = realElement.getParent();
            Object oldResRef = realElement.getResRef();
            TreeElement newElementParent = realParent != null ? getElement(realParent) : null;
            MemoryTreeElement replacement;
            if (org.ogema.core.model.SimpleResource.class.isAssignableFrom(elem.getType())){
                SimpleResourceData data;
                if (elem.isReference()){
                    data = new DefaultSimpleResourceData();
                } else {
                    data = elem.getData();
                }
                replacement = new MemoryTreeElement(elem.getName(), elem.getType(), newElementParent, elem.isDecorator(), data);
            } else {
                replacement = new MemoryTreeElement(elem.getName(), elem.getType(), newElementParent, elem.isDecorator());
            }
                    
            if (oldResRef != null) {
                replacement.setResRef(oldResRef);
            }
            virtualElement.setEl(replacement);
            if (elem.isToplevel()) {
                topLevelElementCache.invalidate(elem.getName());
            }
            realResources.deleteResource(realElement);
            for (DefaultVirtualTreeElement child : virtualElement.getVirtualChildren()) {
            	if (child.isVirtual()) {
            		((MemoryTreeElement) child.getEl()).setParent(replacement);
            	}
            	
            }
        }
    }

    @Override
    public boolean hasResource(String name) {
        return realResources.hasResource(name);
    }

    @Override
    public Collection getAllToplevelResources() {
        Collection real = realResources.getAllToplevelResources();
        Collection rval = new ArrayList<>(real.size());
        for (TreeElement e : real) {
            rval.add(getElement(e));
        }
        return rval;
    }

    @Override
    public void startTransaction() {
    	synchronized (transactionLock) {
	    	if (transactionCounter++ == 0)
	    		realResources.startTransaction();
    	}
    }

    @Override
    public void finishTransaction() {
    	synchronized (transactionLock) {
    		if (--transactionCounter == 0)
    			realResources.finishTransaction();
    		else if (transactionCounter < 0)
    			throw new IllegalStateException("finishTransaction has been called more often than startTransaction");
    	}
    }

    @Override
    public boolean isDBReady() {
        return realResources.isDBReady();
    }

    @Override
    public TreeElement getByID(int id) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public DefaultVirtualTreeElement getElement(TreeElement el) {
    	final String path = el.getPath();
    	DefaultVirtualTreeElement vEl0 = elements.getIfPresent(path);
    	if (vEl0 != null && vEl0.getEl() == el) {
    		return vEl0;
    	}
    	synchronized (this) {
    		while (el instanceof DefaultVirtualTreeElement) {
	            el = ((DefaultVirtualTreeElement) el).getEl();
	        }
	        DefaultVirtualTreeElement vEl = elements.getIfPresent(path);
	        //assert vEl == null || !(el instanceof DefaultVirtualTreeElement) || ((el instanceof DefaultVirtualTreeElement) && el == vEl) : "duplicate DefaultVirtualTreeElement: " + el + " | " + vEl;
	        
	        if (vEl == null) {
	            vEl = new DefaultVirtualTreeElement(el, this);
	            elements.put(path, vEl);
	        } else if (vEl.getEl() != el) {  // FIXME it is unclear here which element is new
	        	//System.out.printf("REPLACE ELEMENT at %s: %s%n", path, el);
	            vEl.setEl(el);
	        }
	        return vEl;
		}
    }
    
    protected synchronized DefaultVirtualTreeElement getElement(String name, TreeElement parent, Class type, boolean decorator) {
        String path = parent.getPath() + "/" + name;
        DefaultVirtualTreeElement vEl = elements.getIfPresent(path);
        if (vEl == null){
            MemoryTreeElement el = new MemoryTreeElement(name, type, parent, decorator);
            vEl = new DefaultVirtualTreeElement(el, this);
            elements.put(path, vEl);
        }
        return vEl;
    }

	@Override
	public Collection getFilteredNodes(Map dict) {
        Collection realElements = realResources.getFilteredNodes(dict);
        Collection vEls = new ArrayList<>(realElements.size());
        for (TreeElement e: realElements) {
            vEls.add(getElement(e));
        }
		return vEls;
	}

	@Override
	public TreeElement getFilteredNodesByPath(String path, boolean isRoot) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Map> getModelDeclaredChildren(String name) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List> getResourceTypesInstalled(Class cls) {
		return realResources.getResourceTypesInstalled(cls);
	}

	@Override
	public void doStorage() {
		// TODO Auto-generated method stub
		
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy