X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.databoard%2Fsrc%2Forg%2Fsimantics%2Fdataboard%2Fbinding%2Freflection%2FBindingRequest.java;h=ac2d9cf1b7246f6be353c8a15aea887ce3b8d45b;hp=4ada936032036b149dd182ac6bb005e138234ffd;hb=95bce3521a3c97f463c3d533a36a606c7ae6f0aa;hpb=0ae2b770234dfc3cbb18bd38f324125cf0faca07 diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/BindingRequest.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/BindingRequest.java index 4ada93603..ac2d9cf1b 100644 --- a/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/BindingRequest.java +++ b/bundles/org.simantics.databoard/src/org/simantics/databoard/binding/reflection/BindingRequest.java @@ -1,3 +1,15 @@ +/******************************************************************************* + * Copyright (c) 2007, 2018 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.reflection; import java.lang.annotation.Annotation; @@ -6,13 +18,25 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; + import org.simantics.databoard.annotations.ArgumentImpl; import org.simantics.databoard.annotations.Arguments; import org.simantics.databoard.binding.Binding; import org.simantics.databoard.primitives.MutableInteger; public class BindingRequest { - + + /** + * A weak cache for signature strings by Class. + * Prevents the system from constructing new strings + * from Classes for every non-trivial BindingRequest. + */ + private static final Map, String> signatureCache = Collections., String>synchronizedMap(new WeakHashMap<>()); + + public static final Annotation[] NO_ANNOTATIONS = {}; + public static BindingRequest create( Field field ) { Annotation[] annotations = ClassBindingFactory.getFieldAnnotations(field); @@ -27,8 +51,6 @@ public class BindingRequest { /** Annotations */ public final Annotation[] annotations; - public final Annotation[] NO_ANNOTATIONS = new Annotation[0]; - public final String className; // eg. java.util.Map public final String signature; // eg. Ljava/util/Map; public final String descriptor; //eg. Ljava/util/Map; @@ -38,6 +60,23 @@ public class BindingRequest { 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. * @@ -54,12 +93,20 @@ public class BindingRequest { this.signature = classSignature; this.annotations = annotations; this.descriptor = classDescriptor; - hash = className.hashCode(); - for (Annotation a : annotations) { - hash = 7*hash + a.hashCode(); - } + hash = calcHash(className); } - + + /** + * Create BindingRequest + * + * @param clazz + * @param annotations + */ + public BindingRequest(Class clazz) + { + this(clazz, NO_ANNOTATIONS); + } + /** * Create BindingRequest * @@ -81,17 +128,23 @@ public class BindingRequest { className = clazz.getCanonicalName(); signature = getSignature(clazz); - List> 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> classes, MutableInteger pos) + + private StringBuilder _buildDescriptor(StringBuilder sb, Class c, List> classes, MutableInteger pos) { int genericCount = c.getTypeParameters().length; int genericsLeft = classes.size()-pos.value; @@ -109,6 +162,7 @@ public class BindingRequest { } else { sb.append( getSignature(c) ); } + return sb; } public BindingRequest(Class clazz, List annotations) @@ -221,8 +275,17 @@ public class BindingRequest { if (clazz==float.class) return "F"; if (clazz==long.class) return "J"; if (clazz==double.class) return "D"; - if (clazz.isArray()) return clazz.getName().replaceAll("\\.", "/"); - return "L"+clazz.getName().replaceAll("\\.", "/")+";"; + String cached = signatureCache.get(clazz); + if (cached == null) { + cached = clazz.isArray() + ? clazz.getName().replace('.', '/') + : "L"+clazz.getName().replace('.', '/')+";"; + signatureCache.put(clazz, cached); + //System.out.println("BindingRequest.getSignature: cache miss for " + clazz + " = " + cached); + } else { + //System.out.println("BindingRequest.getSignature: cache hit for " + clazz + " = " + cached); + } + return cached; } @SuppressWarnings("unchecked")