/******************************************************************************* * Copyright (c) 2007, 2019 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation * Semantum Oy - gitlab #82, gitlab #313 *******************************************************************************/ package org.simantics.databoard.binding.factory; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import org.simantics.databoard.binding.Binding; import org.simantics.databoard.binding.reflection.BindingRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class BindingRepository { private static final Logger LOGGER = LoggerFactory.getLogger(BindingRepository.class); /** * This map contains all the bindings */ Map requestMap; /** * This map contains bindings for non-generic classes. */ Map, Binding> classMap; public BindingRepository() { requestMap = new HashMap(); classMap = new HashMap, Binding>(); } public BindingRepository(Map requests) { this.requestMap = requests; for (Entry e : requests.entrySet()) { if ( isClassRequest( e.getKey() ) ) { registerClassMapping(e.getKey().getClazz(), e.getValue()); } } } /** * Get binding for a class. May return the class if it is in the class map. * If not, the user should try request map with some arguments (component bindings) * * @param clazz * @return binding */ public synchronized Binding get(Class clazz) { return classMap.get( clazz ); } /** * Get binding for a binding request * * @param request * @return binding or null */ public synchronized Binding get( BindingRequest request ) { return requestMap.get( request ); } /** * Adds binding to the repository. If the request has no arguments, the * class is added to classMap, and is available with class request. * * @param request * @param binding */ public synchronized void put( BindingRequest request, Binding binding ) { if ( isClassRequest(request) ) { registerClassMapping(request.getClazz(), binding); } Binding existing = requestMap.put( request, binding ); if (existing != null && !existing.equals(binding)) { LOGGER.error("Replacing existing binding with a different one! {} {} {}", request, binding, existing); } } @SuppressWarnings("unlikely-arg-type") public synchronized void remove(Binding binding) { for (Entry e : requestMap.entrySet()) { if (e.getValue() == binding) { requestMap.remove(e.getValue()); break; } } for (Entry, Binding> e : classMap.entrySet()) { if (e.getValue() == binding) { classMap.remove(e.getValue()); break; } } } public synchronized boolean containsRequest( BindingRequest request ) { return requestMap.containsKey( request ); } /** * Checks if repository contains a class without arguments * * @param clazz * @return true if contains class (without args) */ public synchronized boolean containsClass( Class clazz ) { return classMap.containsKey( clazz ); } public synchronized void clear() { requestMap.clear(); classMap.clear(); } boolean isClassRequest(BindingRequest request) { return (request.className != null && (request.annotations == null || request.annotations.length == 0)); } public void registerClassMapping(Class clazz, Binding binding) { Binding previous = classMap.putIfAbsent(clazz, binding); if (previous != null) { LOGGER.warn("WARN: Can not put same key again to classMap! {} mapping {} not replaced by {}", clazz, previous, binding); } } }