/
HashObject.java
129 lines (104 loc) · 4.55 KB
/
HashObject.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* Copyright (c) 2012-2016 Boundless and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/edl-v10.html
*
* Contributors:
* Johnathan Garrett (LMN Solutions) - initial implementation
*/
package org.locationtech.geogig.plumbing;
import static org.locationtech.geogig.model.RevObject.TYPE.COMMIT;
import static org.locationtech.geogig.model.RevObject.TYPE.FEATURE;
import static org.locationtech.geogig.model.RevObject.TYPE.FEATURETYPE;
import static org.locationtech.geogig.model.RevObject.TYPE.TAG;
import static org.locationtech.geogig.model.RevObject.TYPE.TREE;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import org.eclipse.jdt.annotation.Nullable;
import org.locationtech.geogig.feature.FeatureType;
import org.locationtech.geogig.model.Bucket;
import org.locationtech.geogig.model.HashObjectFunnels;
import org.locationtech.geogig.model.Node;
import org.locationtech.geogig.model.ObjectId;
import org.locationtech.geogig.model.RevObject;
import org.locationtech.geogig.model.RevPerson;
import org.locationtech.geogig.repository.impl.AbstractGeoGigOp;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.hash.Funnel;
import com.google.common.hash.Hasher;
import com.google.common.hash.PrimitiveSink;
import lombok.NonNull;
/**
* Hashes a RevObject and returns the ObjectId.
*
* @see RevObject
* @see ObjectId#HASH_FUNCTION
*/
public class HashObject extends AbstractGeoGigOp<ObjectId> {
@SuppressWarnings("unchecked")
private static final Funnel<? extends RevObject>[] FUNNELS = new Funnel[RevObject.TYPE
.values().length];
static {
FUNNELS[COMMIT.value()] = HashObjectFunnels.commitFunnel();
FUNNELS[TREE.value()] = HashObjectFunnels.treeFunnel();
FUNNELS[FEATURE.value()] = HashObjectFunnels.featureFunnel();
FUNNELS[TAG.value()] = HashObjectFunnels.tagFunnel();
FUNNELS[FEATURETYPE.value()] = HashObjectFunnels.featureTypeFunnel();
}
private RevObject object;
/**
* @param object {@link RevObject} to hash.
* @return {@code this}
*/
public HashObject setObject(RevObject object) {
this.object = object;
return this;
}
/**
* Hashes a RevObject using a SHA1 hasher.
*
* @return a new ObjectId created from the hash of the RevObject.
*/
protected @Override ObjectId _call() {
Preconditions.checkState(object != null, "Object has not been set.");
final Hasher hasher = ObjectId.HASH_FUNCTION.newHasher();
@SuppressWarnings("unchecked")
final Funnel<RevObject> funnel = (Funnel<RevObject>) FUNNELS[object.getType().value()];
funnel.funnel(object, hasher);
final byte[] rawKey = hasher.hash().asBytes();
final ObjectId id = ObjectId.create(rawKey);
return id;
}
public static ObjectId hashFeature(List<Object> values) {
return hash(h -> HashObjectFunnels.feature(h, values));
}
public static ObjectId hashTree(@Nullable List<Node> trees, @Nullable List<Node> features,
@Nullable Iterable<Bucket> buckets) {
final List<Node> t = trees == null ? ImmutableList.of() : trees;
final List<Node> f = features == null ? ImmutableList.of() : features;
final Iterable<Bucket> b = buckets == null ? Collections.emptySet() : buckets;
return hash(h -> HashObjectFunnels.tree(h, t, f, b));
}
public static ObjectId hashTag(String name, ObjectId commitId, String message,
RevPerson tagger) {
return hash(h -> HashObjectFunnels.tag(h, name, commitId, message, tagger));
}
public static ObjectId hashFeatureType(@NonNull FeatureType featureType) {
return hash(h -> HashObjectFunnels.featureType(h, featureType));
}
public static ObjectId hashCommit(ObjectId treeId, List<ObjectId> parentIds, RevPerson author,
RevPerson committer, String commitMessage) {
return hash(h -> HashObjectFunnels.commit(h, treeId, parentIds, author, committer,
commitMessage));
}
private static ObjectId hash(Consumer<PrimitiveSink> funnel) {
final Hasher hasher = ObjectId.HASH_FUNCTION.newHasher();
funnel.accept(hasher);
final byte[] rawKey = hasher.hash().asBytes();
final ObjectId id = ObjectId.create(rawKey);
return id;
}
}