[Java] Generate copy constructor in models
Description
Java models should have a way to easily create a clone or copy. Cloneable seems like a bad idea so I think we're probably left with a copy function or copy constructor.
I couldn't find anything in issues search. Has this been suggested before?
@asarazan I don't recall anyone suggesting something similar.
Just so you know we can make the model "Serializable" by switching on an option. For cloneable or copy we can do something similar.
That sounds good. I've been re-reading the Effective Java entry on Cloneable and I'm convinced it's probably the wrong decision:
Suppose you want to make this class cloneable. If its clone method merely returns super.clone() , the resulting Stack instance will have the correct value in its size field, but its elements field will refer to the same array as the original Stack instance. Modifying the original will destroy the invariants in the clone and vice versa. You will quickly find that your program produces nonsensical results or throws a NullPointerException .
So it looks like anything with mutable state becomes very very fragile with clone. It seems like the best way forward is to generate a field-by-field copy constructor for each model, which defensively deep copies each property.
Alternately, a good (but difficult) long-term solution would be to re-architect models as immutable data objects with a builder pattern for mutation-- e.g. how protocol buffers is implemented.
One good use case for this is if you are accessing the swagger endpoint with different host names and want the host name to be based on the request URI's host. I think we just need a shallow copy constructor. Something like withBaseUri
package net.trajano.ms.engine.internal.swagger;
import java.net.URI;
import java.util.Arrays;
import io.swagger.models.Scheme;
import io.swagger.models.Swagger;
public class ClonableSwagger extends Swagger {
/**
* Creates a shallow copy of the swagger but set the scheme, host and base path
* to the base URI
*
* @param baseUri
* base URI
* @return shallow copy
*/
public ClonableSwagger withBaseUri(final URI baseUri) {
final ClonableSwagger copy = new ClonableSwagger();
copy.swagger = swagger;
copy.info = info;
if (baseUri.getPort() > 0) {
copy.host = baseUri.getHost() + ":" + baseUri.getPort();
} else {
copy.host = baseUri.getHost();
}
copy.basePath = baseUri.getPath();
copy.tags = tags;
copy.schemes = Arrays.asList(Scheme.forValue(baseUri.getScheme()));
copy.consumes = consumes;
copy.produces = produces;
copy.security = security;
copy.paths = paths;
copy.securityDefinitions = securityDefinitions;
copy.definitions = definitions;
copy.parameters = parameters;
copy.responses = responses;
copy.externalDocs = externalDocs;
copy.vendorExtensions = vendorExtensions;
return copy;
}
}
Any news about this ? I need to clone Schema object, should i make an utility method to clone this object in my project, or do you want a pull request with this kind of feature ?
I checked serialization part and made little util function for creating copy for editing
private <T> T getCopy(T src) {
Gson gson=yourWayForGettingApiClient().getJSON().getGson();
String s=gson.toJson(src);
Class<T> clazz=(Class<T>) src.getClass();
T copy=gson.fromJson(s,clazz);
return copy;
}