Browse Source

Allow identical data to be published if the metadata differs.

qdn-metadata
CalDescent 3 years ago
parent
commit
cbd1018ecf
  1. 53
      src/main/java/org/qortal/arbitrary/ArbitraryDataTransactionBuilder.java
  2. 9
      src/main/java/org/qortal/arbitrary/metadata/ArbitraryDataTransactionMetadata.java

53
src/main/java/org/qortal/arbitrary/ArbitraryDataTransactionBuilder.java

@ -6,6 +6,7 @@ import org.qortal.arbitrary.exception.MissingDataException;
import org.qortal.arbitrary.ArbitraryDataFile.ResourceIdType; import org.qortal.arbitrary.ArbitraryDataFile.ResourceIdType;
import org.qortal.arbitrary.ArbitraryDataDiff.*; import org.qortal.arbitrary.ArbitraryDataDiff.*;
import org.qortal.arbitrary.metadata.ArbitraryDataMetadataPatch; import org.qortal.arbitrary.metadata.ArbitraryDataMetadataPatch;
import org.qortal.arbitrary.metadata.ArbitraryDataTransactionMetadata;
import org.qortal.arbitrary.misc.Category; import org.qortal.arbitrary.misc.Category;
import org.qortal.arbitrary.misc.Service; import org.qortal.arbitrary.misc.Service;
import org.qortal.crypto.Crypto; import org.qortal.crypto.Crypto;
@ -27,6 +28,7 @@ import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.Random; import java.util.Random;
public class ArbitraryDataTransactionBuilder { public class ArbitraryDataTransactionBuilder {
@ -79,9 +81,9 @@ public class ArbitraryDataTransactionBuilder {
this.identifier = identifier; this.identifier = identifier;
// Metadata (optional) // Metadata (optional)
this.title = title; this.title = ArbitraryDataTransactionMetadata.limitTitle(title);
this.description = description; this.description = ArbitraryDataTransactionMetadata.limitDescription(description);
this.tags = tags; this.tags = ArbitraryDataTransactionMetadata.limitTags(tags);
this.category = category; this.category = category;
} }
@ -121,6 +123,10 @@ public class ArbitraryDataTransactionBuilder {
return Method.PUT; return Method.PUT;
} }
// Get existing metadata and see if it matches the new metadata
ArbitraryDataResource resource = new ArbitraryDataResource(this.name, ResourceIdType.NAME, this.service, this.identifier);
ArbitraryDataTransactionMetadata existingMetadata = resource.getLatestTransactionMetadata();
try { try {
// Check layer count // Check layer count
int layerCount = reader.getLayerCount(); int layerCount = reader.getLayerCount();
@ -131,7 +137,23 @@ public class ArbitraryDataTransactionBuilder {
// Check size of differences between this layer and previous layer // Check size of differences between this layer and previous layer
ArbitraryDataCreatePatch patch = new ArbitraryDataCreatePatch(reader.getFilePath(), this.path, reader.getLatestSignature()); ArbitraryDataCreatePatch patch = new ArbitraryDataCreatePatch(reader.getFilePath(), this.path, reader.getLatestSignature());
patch.create(); try {
patch.create();
}
catch (DataException | IOException e) {
// Handle matching states separately, as it's best to block transactions with duplicate states
if (e.getMessage().equals("Current state matches previous state. Nothing to do.")) {
// Only throw an exception if the metadata is also identical, as well as the data
if (this.isMetadataEqual(existingMetadata)) {
throw new DataException(e.getMessage());
}
}
LOGGER.info("Caught exception when creating patch: {}", e.getMessage());
LOGGER.info("Unable to load existing resource - using PUT to overwrite it.");
return Method.PUT;
}
long diffSize = FilesystemUtils.getDirectorySize(patch.getFinalPath()); long diffSize = FilesystemUtils.getDirectorySize(patch.getFinalPath());
long existingStateSize = FilesystemUtils.getDirectorySize(reader.getFilePath()); long existingStateSize = FilesystemUtils.getDirectorySize(reader.getFilePath());
double difference = (double) diffSize / (double) existingStateSize; double difference = (double) diffSize / (double) existingStateSize;
@ -168,11 +190,8 @@ public class ArbitraryDataTransactionBuilder {
// State is appropriate for a PATCH transaction // State is appropriate for a PATCH transaction
return Method.PATCH; return Method.PATCH;
} }
catch (IOException | DataException e) { catch (IOException e) {
// Handle matching states separately, as it's best to block transactions with duplicate states // IMPORTANT: Don't catch DataException here, as they must be passed to the caller
if (e.getMessage().equals("Current state matches previous state. Nothing to do.")) {
throw new DataException(e.getMessage());
}
LOGGER.info("Caught exception: {}", e.getMessage()); LOGGER.info("Caught exception: {}", e.getMessage());
LOGGER.info("Unable to load existing resource - using PUT to overwrite it."); LOGGER.info("Unable to load existing resource - using PUT to overwrite it.");
return Method.PUT; return Method.PUT;
@ -267,6 +286,22 @@ public class ArbitraryDataTransactionBuilder {
} }
private boolean isMetadataEqual(ArbitraryDataTransactionMetadata existingMetadata) {
if (!Objects.equals(existingMetadata.getTitle(), this.title)) {
return false;
}
if (!Objects.equals(existingMetadata.getDescription(), this.description)) {
return false;
}
if (!Objects.equals(existingMetadata.getCategory(), this.category)) {
return false;
}
if (!Objects.equals(existingMetadata.getTags(), this.tags)) {
return false;
}
return true;
}
public void computeNonce() throws DataException { public void computeNonce() throws DataException {
if (this.arbitraryTransactionData == null) { if (this.arbitraryTransactionData == null) {
throw new DataException("Arbitrary transaction data is required to compute nonce"); throw new DataException("Arbitrary transaction data is required to compute nonce");

9
src/main/java/org/qortal/arbitrary/metadata/ArbitraryDataTransactionMetadata.java

@ -172,6 +172,9 @@ public class ArbitraryDataTransactionMetadata extends ArbitraryDataMetadata {
if (title == null) { if (title == null) {
return null; return null;
} }
if (title.isEmpty()) {
return null;
}
return title.substring(0, Math.min(title.length(), MAX_TITLE_LENGTH)); return title.substring(0, Math.min(title.length(), MAX_TITLE_LENGTH));
} }
@ -180,6 +183,9 @@ public class ArbitraryDataTransactionMetadata extends ArbitraryDataMetadata {
if (description == null) { if (description == null) {
return null; return null;
} }
if (description.isEmpty()) {
return null;
}
return description.substring(0, Math.min(description.length(), MAX_DESCRIPTION_LENGTH)); return description.substring(0, Math.min(description.length(), MAX_DESCRIPTION_LENGTH));
} }
@ -199,10 +205,11 @@ public class ArbitraryDataTransactionMetadata extends ArbitraryDataMetadata {
// Remove tags over the limit // Remove tags over the limit
// This is cleaner than truncating, which results in malformed tags // This is cleaner than truncating, which results in malformed tags
// Also remove tags that are empty
Iterator iterator = mutableTags.iterator(); Iterator iterator = mutableTags.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
String tag = (String) iterator.next(); String tag = (String) iterator.next();
if (tag == null || tag.length() > MAX_TAG_LENGTH) { if (tag == null || tag.length() > MAX_TAG_LENGTH || tag.isEmpty()) {
iterator.remove(); iterator.remove();
} }
} }

Loading…
Cancel
Save