]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/binding/factory/BindingRepository.java
Fixing several binding-related bugs
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / binding / factory / BindingRepository.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2019 Association for Decentralized Information Management in
3  * Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *     Semantum Oy - gitlab #82, gitlab #313
12  *******************************************************************************/
13 package org.simantics.databoard.binding.factory;
14
15 import java.util.HashMap;
16 import java.util.Map;
17 import java.util.Map.Entry;
18
19 import org.simantics.databoard.binding.Binding;
20 import org.simantics.databoard.binding.reflection.BindingRequest;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 public class BindingRepository {
25
26     private static final Logger LOGGER = LoggerFactory.getLogger(BindingRepository.class);
27         /**
28          * This map contains all the bindings
29          */
30         Map<BindingRequest, Binding> requestMap;
31         
32         /**
33          * This map contains bindings for non-generic classes. 
34          */
35         Map<Class<?>, Binding> classMap;
36         
37         public BindingRepository() {            
38                 requestMap = new HashMap<BindingRequest, Binding>();
39                 classMap = new HashMap<Class<?>, Binding>();
40         }
41         
42         public BindingRepository(Map<BindingRequest, Binding> requests) {
43                 this.requestMap = requests;
44                 for (Entry<BindingRequest, Binding> e : requests.entrySet()) {
45                         if ( isClassRequest( e.getKey() ) ) {
46                                 registerClassMapping(e.getKey().getClazz(), e.getValue());
47                         }
48                 }
49         }
50         
51         /**
52          * Get binding for a class. May return the class if it is in the class map.
53          * If not, the user should try request map with some arguments (component bindings)
54          * 
55          * @param clazz
56          * @return binding
57          */
58         public synchronized Binding get(Class<?> clazz) {
59                 return classMap.get( clazz );
60         }
61         
62         /**
63          * Get binding for a binding request
64          * 
65          * @param request
66          * @return binding or null
67          */
68         public synchronized Binding get( BindingRequest request ) {
69                 return requestMap.get( request );
70         }
71         
72         /**
73          * Adds binding to the repository. If the request has no arguments, the 
74          * class is added to classMap, and is available with class request.  
75          * 
76          * @param request
77          * @param binding
78          */
79         public synchronized void put( BindingRequest request, Binding binding ) {
80                 if ( isClassRequest(request) ) {
81                     registerClassMapping(request.getClazz(), binding);
82                 }
83                 Binding existing = requestMap.put( request, binding );
84                 if (existing != null && !existing.equals(binding)) {
85                     LOGGER.error("Replacing existing binding with a different one! {} {} {}", request, binding, existing);
86                 }
87         }
88
89         @SuppressWarnings("unlikely-arg-type")
90         public synchronized void remove(Binding binding) {
91                 for (Entry<BindingRequest, Binding> e : requestMap.entrySet()) {
92                         if (e.getValue() == binding) {
93                                 requestMap.remove(e.getValue());
94                                 break;
95                         }
96                 }
97                 
98                 for (Entry<Class<?>, Binding> e : classMap.entrySet()) {
99                         if (e.getValue() == binding) {
100                                 classMap.remove(e.getValue());
101                                 break;
102                         }
103                 }
104 }
105         
106         public synchronized boolean containsRequest( BindingRequest request ) {
107                 return requestMap.containsKey( request );
108         }
109         
110         /**
111          * Checks if repository contains a class without arguments
112          * 
113          * @param clazz 
114          * @return true if contains class (without args)
115          */
116         public synchronized boolean containsClass( Class<?> clazz ) {
117                 return classMap.containsKey( clazz );
118         }
119         
120         public synchronized void clear() {
121                 requestMap.clear();
122                 classMap.clear();
123         }
124
125         boolean isClassRequest(BindingRequest request) {
126                 return (request.className != null && (request.annotations == null || request.annotations.length == 0));
127         }
128
129         public void registerClassMapping(Class<?> clazz, Binding binding) {
130                 Binding previous = classMap.putIfAbsent(clazz, binding);
131                 if (previous != null) {
132                         LOGGER.warn("WARN: Can not put same key again to classMap! {} mapping {} not replaced by {}", clazz, previous, binding);
133                 }
134         }
135
136 }