Changeset View
Changeset View
Standalone View
Standalone View
java/src/main/java/org/softwareheritage/graph/SWHID.java
- This file was moved from java/src/main/java/org/softwareheritage/graph/SwhPID.java.
package org.softwareheritage.graph; | package org.softwareheritage.graph; | ||||
import com.fasterxml.jackson.annotation.JsonValue; | import com.fasterxml.jackson.annotation.JsonValue; | ||||
import org.apache.commons.codec.DecoderException; | import org.apache.commons.codec.DecoderException; | ||||
import org.apache.commons.codec.binary.Hex; | import org.apache.commons.codec.binary.Hex; | ||||
/** | /** | ||||
* A Software Heritage PID, see <a | * A Software Heritage persistent identifier (SWHID), see <a | ||||
* href="https://docs.softwareheritage.org/devel/swh-model/persistent-identifiers.html#persistent-identifiers">persistent | * href="https://docs.softwareheritage.org/devel/swh-model/persistent-identifiers.html#persistent-identifiers">persistent | ||||
* identifier documentation</a>. | * identifier documentation</a>. | ||||
* | * | ||||
* @author The Software Heritage developers | * @author The Software Heritage developers | ||||
*/ | */ | ||||
public class SwhPID { | public class SWHID { | ||||
/** Fixed hash length of the PID */ | /** Fixed hash length of the SWHID */ | ||||
public static final int HASH_LENGTH = 40; | public static final int HASH_LENGTH = 40; | ||||
/** Full PID as a string */ | /** Full SWHID as a string */ | ||||
String swhPID; | String swhid; | ||||
/** PID node type */ | /** SWHID node type */ | ||||
Node.Type type; | Node.Type type; | ||||
/** | /** | ||||
* Constructor. | * Constructor. | ||||
* | * | ||||
* @param swhPID full PID as a string | * @param swhid full SWHID as a string | ||||
*/ | */ | ||||
public SwhPID(String swhPID) { | public SWHID(String swhid) { | ||||
this.swhPID = swhPID; | this.swhid = swhid; | ||||
// PID format: 'swh:1:type:hash' | // SWHID format: 'swh:1:type:hash' | ||||
String[] parts = swhPID.split(":"); | String[] parts = swhid.split(":"); | ||||
if (parts.length != 4 || !parts[0].equals("swh") || !parts[1].equals("1")) { | if (parts.length != 4 || !parts[0].equals("swh") || !parts[1].equals("1")) { | ||||
throw new IllegalArgumentException("malformed SWH PID: " + swhPID); | throw new IllegalArgumentException("malformed SWHID: " + swhid); | ||||
} | } | ||||
this.type = Node.Type.fromStr(parts[2]); | this.type = Node.Type.fromStr(parts[2]); | ||||
if (!parts[3].matches("[0-9a-f]{" + HASH_LENGTH + "}")) { | if (!parts[3].matches("[0-9a-f]{" + HASH_LENGTH + "}")) { | ||||
throw new IllegalArgumentException("malformed SWH PID: " + swhPID); | throw new IllegalArgumentException("malformed SWHID: " + swhid); | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Creates a SwhPID from a compact binary representation. | * Creates a SWHID from a compact binary representation. | ||||
* <p> | * <p> | ||||
* The binary format is specified in the Python module | * The binary format is specified in the Python module | ||||
* swh.graph.pid:str_to_bytes . | * swh.graph.swhid:str_to_bytes . | ||||
*/ | */ | ||||
public static SwhPID fromBytes(byte[] input) { | public static SWHID fromBytes(byte[] input) { | ||||
byte[] digest = new byte[20]; | byte[] digest = new byte[20]; | ||||
System.arraycopy(input, 2, digest, 0, digest.length); | System.arraycopy(input, 2, digest, 0, digest.length); | ||||
String pidStr = String.format( | String swhidStr = String.format( | ||||
"swh:%d:%s:%s", | "swh:%d:%s:%s", | ||||
input[0], | input[0], | ||||
Node.Type.fromInt(input[1]).toString().toLowerCase(), | Node.Type.fromInt(input[1]).toString().toLowerCase(), | ||||
Hex.encodeHexString(digest) | Hex.encodeHexString(digest) | ||||
); | ); | ||||
return new SwhPID(pidStr); | return new SWHID(swhidStr); | ||||
} | } | ||||
@Override | @Override | ||||
public boolean equals(Object otherObj) { | public boolean equals(Object otherObj) { | ||||
if (otherObj == this) | if (otherObj == this) | ||||
return true; | return true; | ||||
if (!(otherObj instanceof SwhPID)) | if (!(otherObj instanceof SWHID)) | ||||
return false; | return false; | ||||
SwhPID other = (SwhPID) otherObj; | SWHID other = (SWHID) otherObj; | ||||
return swhPID.equals(other.getSwhPID()); | return swhid.equals(other.getSWHID()); | ||||
} | } | ||||
@Override | @Override | ||||
public int hashCode() { | public int hashCode() { | ||||
return swhPID.hashCode(); | return swhid.hashCode(); | ||||
} | } | ||||
@Override | @Override | ||||
public String toString() { | public String toString() { | ||||
return swhPID; | return swhid; | ||||
} | } | ||||
/** | /** | ||||
* Converts PID to a compact binary representation. | * Converts SWHID to a compact binary representation. | ||||
* <p> | * <p> | ||||
* The binary format is specified in the Python module | * The binary format is specified in the Python module | ||||
* swh.graph.pid:str_to_bytes . | * swh.graph.swhid:str_to_bytes . | ||||
*/ | */ | ||||
public byte[] toBytes() { | public byte[] toBytes() { | ||||
byte[] bytes = new byte[22]; | byte[] bytes = new byte[22]; | ||||
byte[] digest; | byte[] digest; | ||||
bytes[0] = (byte) 1; // namespace version | bytes[0] = (byte) 1; // namespace version | ||||
bytes[1] = (byte) Node.Type.toInt(this.type); // PID type | bytes[1] = (byte) Node.Type.toInt(this.type); // SWHID type | ||||
try { | try { | ||||
digest = Hex.decodeHex(this.swhPID.substring(10)); // SHA1 hash | digest = Hex.decodeHex(this.swhid.substring(10)); // SHA1 hash | ||||
System.arraycopy(digest, 0, bytes, 2, digest.length); | System.arraycopy(digest, 0, bytes, 2, digest.length); | ||||
} catch (DecoderException e) { | } catch (DecoderException e) { | ||||
throw new IllegalArgumentException("invalid hex sequence in PID: " + this.swhPID); | throw new IllegalArgumentException("invalid hex sequence in SWHID: " + this.swhid); | ||||
} | } | ||||
return bytes; | return bytes; | ||||
} | } | ||||
/** | /** | ||||
* Returns full PID as a string. | * Returns full SWHID as a string. | ||||
* | * | ||||
* @return full PID string | * @return full SWHID string | ||||
*/ | */ | ||||
@JsonValue | @JsonValue | ||||
public String getSwhPID() { | public String getSWHID() { | ||||
return swhPID; | return swhid; | ||||
} | } | ||||
/** | /** | ||||
* Returns PID node type. | * Returns SWHID node type. | ||||
* | * | ||||
* @return PID corresponding {@link Node.Type} | * @return SWHID corresponding {@link Node.Type} | ||||
* @see org.softwareheritage.graph.Node.Type | * @see org.softwareheritage.graph.Node.Type | ||||
*/ | */ | ||||
public Node.Type getType() { | public Node.Type getType() { | ||||
return type; | return type; | ||||
} | } | ||||
} | } |