Remove AbstractExplicitGenerator.recursiveRuntimeType()
[mdsal.git] / binding / mdsal-binding-generator / src / main / java / org / opendaylight / mdsal / binding / generator / impl / reactor / SerialVersionHelper.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.mdsal.binding.generator.impl.reactor;
9
10 import com.google.common.collect.Collections2;
11 import java.io.ByteArrayOutputStream;
12 import java.io.DataOutputStream;
13 import java.io.IOException;
14 import java.security.MessageDigest;
15 import java.security.NoSuchAlgorithmException;
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.Comparator;
19 import java.util.List;
20 import java.util.Set;
21 import org.opendaylight.mdsal.binding.model.api.AccessModifier;
22 import org.opendaylight.mdsal.binding.model.api.ConcreteType;
23 import org.opendaylight.mdsal.binding.model.api.Type;
24 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedPropertyBuilder;
25 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
26 import org.opendaylight.mdsal.binding.model.api.type.builder.MethodSignatureBuilder;
27 import org.opendaylight.mdsal.binding.model.api.type.builder.TypeMemberBuilder;
28 import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
29
30 public final class SerialVersionHelper {
31     private static final Set<ConcreteType> IGNORED_INTERFACES =
32         Set.of(BindingTypes.TYPE_OBJECT, BindingTypes.SCALAR_TYPE_OBJECT);
33     private static final Comparator<TypeMemberBuilder<?>> SUID_MEMBER_COMPARATOR =
34         Comparator.comparing(TypeMemberBuilder::getName);
35     private static final Comparator<Type> SUID_NAME_COMPARATOR = Comparator.comparing(Type::getFullyQualifiedName);
36     private static final ThreadLocal<MessageDigest> SHA1_MD = ThreadLocal.withInitial(() -> {
37         try {
38             return MessageDigest.getInstance("SHA");
39         } catch (final NoSuchAlgorithmException e) {
40             throw new IllegalStateException("Failed to get a SHA digest provider", e);
41         }
42     });
43
44     private SerialVersionHelper() {
45         // Hidden on purpose
46     }
47
48     public static long computeDefaultSUID(final GeneratedTypeBuilderBase<?> to) {
49         final ByteArrayOutputStream bout = new ByteArrayOutputStream();
50         try (DataOutputStream dout = new DataOutputStream(bout)) {
51             dout.writeUTF(to.getName());
52             dout.writeInt(to.isAbstract() ? 3 : 7);
53
54             for (final Type ifc : sortedCollection(SUID_NAME_COMPARATOR, filteredImplementsTypes(to))) {
55                 dout.writeUTF(ifc.getFullyQualifiedName());
56             }
57
58             for (final GeneratedPropertyBuilder gp : sortedCollection(SUID_MEMBER_COMPARATOR, to.getProperties())) {
59                 dout.writeUTF(gp.getName());
60             }
61
62             for (final MethodSignatureBuilder m : sortedCollection(SUID_MEMBER_COMPARATOR, to.getMethodDefinitions())) {
63                 if (!m.getAccessModifier().equals(AccessModifier.PRIVATE)) {
64                     dout.writeUTF(m.getName());
65                     dout.write(m.getAccessModifier().ordinal());
66                 }
67             }
68
69             dout.flush();
70         } catch (final IOException e) {
71             throw new IllegalStateException("Failed to hash object " + to, e);
72         }
73
74         final byte[] hashBytes = SHA1_MD.get().digest(bout.toByteArray());
75         long hash = 0;
76         for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
77             hash = hash << 8 | hashBytes[i] & 0xFF;
78         }
79         return hash;
80     }
81
82     private static Collection<Type> filteredImplementsTypes(final GeneratedTypeBuilderBase<?> to) {
83         return Collections2.filter(to.getImplementsTypes(), item -> !IGNORED_INTERFACES.contains(item));
84     }
85
86     private static <T> Iterable<T> sortedCollection(final Comparator<? super T> comparator, final Collection<T> input) {
87         if (input.size() <= 1) {
88             return input;
89         }
90
91         final List<T> ret = new ArrayList<>(input);
92         ret.sort(comparator);
93         return ret;
94     }
95 }