*
* Contributors:
* VTT Technical Research Centre of Finland - initial API and implementation
+ * Semantum Oy - gitlab #313
*******************************************************************************/
package org.simantics.databoard;
databoard.initialize();
- DATATYPE = getBindingUnchecked(Datatype.class);
+ DATATYPE = getBindingUnchecked(Datatype.class);
+ /**
+ * {@link Datatype} class has annotations but it can be considered a "class
+ * request" as it is a fundamental building block of Databoard and it has a
+ * fixed structure. Therefore {@link BindingRepository#classMap} is allowed
+ * to contain a cached Datatype.class -> Binding mapping.
+ */
+ bindingRepository.registerClassMapping(Datatype.class, DATATYPE);
}
}
/*******************************************************************************
- * Copyright (c) 2007, 2018 Association for Decentralized Information Management in
+ * 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
*
* Contributors:
* VTT Technical Research Centre of Finland - initial API and implementation
- * Semantum Oy - gitlab #82
+ * Semantum Oy - gitlab #82, gitlab #313
*******************************************************************************/
package org.simantics.databoard.binding.factory;
import org.simantics.databoard.binding.Binding;
import org.simantics.databoard.binding.reflection.BindingRequest;
-import org.simantics.databoard.type.Datatype;
+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
*/
this.requestMap = requests;
for (Entry<BindingRequest, Binding> e : requests.entrySet()) {
if ( isClassRequest( e.getKey() ) ) {
- classMap.put(e.getKey().getClazz(), e.getValue());
+ registerClassMapping(e.getKey().getClazz(), e.getValue());
}
}
}
*/
public synchronized void put( BindingRequest request, Binding binding ) {
if ( isClassRequest(request) ) {
- classMap.put( request.getClazz(), binding );
+ 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);
}
- requestMap.put( request, binding );
}
-
+
+ @SuppressWarnings("unlikely-arg-type")
public synchronized void remove(Binding binding) {
for (Entry<BindingRequest, Binding> e : requestMap.entrySet()) {
if (e.getValue() == binding) {
classMap.clear();
}
- /**
- * {@link Datatype} class has annotations but it can be considered a "class
- * request" as it is a fundamental building block of Databoard and it has a
- * fixed structure. Therefore {@link #classMap} is allowed to contain a cached
- * Datatype.class -> Binding mapping.
- */
- private static final String DATATYPE_CLASS_NAME = Datatype.class.getName();
+ boolean isClassRequest(BindingRequest request) {
+ return (request.className != null && (request.annotations == null || request.annotations.length == 0));
+ }
- boolean isClassRequest( BindingRequest request )
- {
- return (request.className != null
- && ((request.annotations==null || request.annotations.length==0)
- || DATATYPE_CLASS_NAME.equals(request.className))
- );
+ 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);
+ }
}
}
*
* Contributors:
* VTT Technical Research Centre of Finland - initial API and implementation
- * Semantum Oy - gitlab #82
+ * Semantum Oy - gitlab #82, gitlab #313
*******************************************************************************/
package org.simantics.databoard.binding.reflection;
transient int hash;
+ /**
+ * Cloning constructor with replacement annotations.
+ *
+ * @param other the request to clone
+ * @param annotations the annotations to use while cloning
+ */
+ private BindingRequest(BindingRequest other, Annotation...annotations)
+ {
+ this.clazz = other.clazz;
+ this.cl = other.cl;
+ this.annotations = annotations;
+ this.className = other.className;
+ this.signature = other.signature;
+ this.descriptor = other.descriptor;
+ hash = calcHash(clazz.getName());
+ }
+
/**
* Create BindingRequest that creates class lazily.
*
this.signature = classSignature;
this.annotations = annotations;
this.descriptor = classDescriptor;
- hash = className.hashCode();
- for (Annotation a : annotations) {
- hash = 7*hash + a.hashCode();
- }
+ hash = calcHash(className);
}
/**
className = clazz.getCanonicalName();
signature = getSignature(clazz);
- List<Class<?>> args = createArgsList();
- StringBuilder desc = new StringBuilder();
- _buildDescriptor(desc, clazz, args, new MutableInteger(0));
- descriptor = desc.toString();
- hash = clazz.getName().hashCode();
- for (Annotation a : annotations) {
- hash = 7*hash + a.hashCode();
+ descriptor = _buildDescriptor(new StringBuilder(), clazz, createArgsList(), new MutableInteger(0)).toString();
+ hash = calcHash(clazz.getName());
+ }
+
+ public BindingRequest withAnnotations(Annotation... newAnnotations) {
+ return new BindingRequest(this, newAnnotations);
+ }
+
+ private int calcHash(String className) {
+ int hash = className.hashCode();
+ for (Annotation a : this.annotations) {
+ hash += a.hashCode();
}
+ return hash;
}
-
- private void _buildDescriptor(StringBuilder sb, Class<?> c, List<Class<?>> classes, MutableInteger pos)
+
+ private StringBuilder _buildDescriptor(StringBuilder sb, Class<?> c, List<Class<?>> classes, MutableInteger pos)
{
int genericCount = c.getTypeParameters().length;
int genericsLeft = classes.size()-pos.value;
} else {
sb.append( getSignature(c) );
}
+ return sb;
}
public BindingRequest(Class<?> clazz, List<Annotation> annotations)
+/*******************************************************************************
+ * Copyright (c) 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 #313
+ *******************************************************************************/
package org.simantics.databoard.binding.reflection;
import java.lang.annotation.Annotation;
if(request.hasAnnotation(Optional.class))
{
Optional optional = request.getAnnotation(Optional.class);
- Annotation[] newAnnotations = ArrayUtils.dropElements(request.annotations, optional);
- BindingRequest componentRequest = new BindingRequest(request.getClazz(), newAnnotations);
+ BindingRequest componentRequest = request.withAnnotations(ArrayUtils.dropElements(request.annotations, optional));
OptionalType type = new OptionalType();
OptionalBinding binding = new OptionalBindingDefault(type, null);
inprogress.put(request, binding);
type.componentType = binding.componentBinding.type();
inprogress.remove(request);
+ repository.put(request, binding);
return binding;
}
Identifier idAnnotation = componentRequest.getAnnotation( Identifier.class );
if ( idAnnotation!=null ) {
- componentRequest.dropAnnotations(1, idAnnotation);
+ componentRequest = componentRequest.withAnnotations(componentRequest.dropAnnotations(1, idAnnotation));
identifierIndices.add( i );
}
Binding componentBinding = componentBindings[i] = construct( componentRequest );
binding = defaultBinding;
}
- repository.put(request, binding);
-
return binding;
} catch (RangeException e) {
inprogress.remove( request );