generate CURL from java.net.http.HttpRequest - java

is there a good way to generate curl from java.net.http.HttpRequest? It seems like there is no good way to get the body (if there is a body), the closest thing to it is bodyPublisher() that returns Optional<BodyPublisher> that has only long contentLength() method.

Indeed, it's way trickier than it looks like.
The HttpRequest of java.net.http package is a generic object that can be used as request for any type of HttpClient<?>, hence it doesn't know what the body is, and generically provides a body publisher (type unknown) to which subscribers of a specific type can subscribe in a custom way in order to get the content from it.
This is very different from HttpResponse<?>, that you usually get from a HttpClient<?> with a specific type (usually String) and that can so trivially return you a String getBody().
If you don't want to use any third-party library (which already implement the below logic), this is the way you can extract the (String) body from the publisher:
String requestBody = httpRequest.bodyPublisher().map(p -> {
HttpResponse.BodySubscriber<String> bodySubscriber = HttpResponse.BodySubscribers.ofString(StandardCharsets.UTF_8);
StringSubscriber stringSubscriber = new StringSubscriber(bodySubscriber);
p.subscribe(stringSubscriber);
return bodySubscriber.getBody().toCompletableFuture().join();
}).orElse("");
... where httpRequest is your java.net.http.HttpRequest and StringSubscriber is an implementation of Flow.Subscriber<ByteBuffer> like follows:
class StringSubscriber implements Flow.Subscriber<ByteBuffer> {
private final HttpResponse.BodySubscriber<String> wrapped;
private StringSubscriber(HttpResponse.BodySubscriber<String> wrapped) {
this.wrapped = wrapped;
}
#Override
public void onSubscribe(Flow.Subscription subscription) {
wrapped.onSubscribe(subscription);
}
#Override
public void onNext(ByteBuffer item) {
wrapped.onNext(List.of(item));
}
#Override
public void onError(Throwable throwable) {
wrapped.onError(throwable);
}
#Override
public void onComplete() {
wrapped.onComplete();
}
}
Explanation:
If there is no BodyPublisher in your request, you simply return an empty string (assuming that means no body, you can customize it to null or whatever you want).
Else, if there is a BodyPublisher in your request, then you will do the following:
You will create a BodySubscriber of type String (meaning you will subscribe to a publisher that can provide a String version of its body)
Create a new instance of StringSubscriber (your own implementation that I posted above)
Subscribe to the publisher with your subscriber, so that the publisher can call you back with the stream content.
Get the future result (containing the body) when you're called back from the publisher (the call is asynchronous so you need to .join() it)

Related

Return value of an AWS (Java) Lambda function

Suppose I have the following code
public final class MyLambdaFunction implements RequestHandler<SQSEvent, String> {
#Override
public String handleRequest(SQSEvent event, Context context) {
return "Hello World";
}
}
I don't understand the purpose of having an output value (a String, in the example above), so I was wondering if I can use that value somewhere else (e.g. automatically send the return value to another SQS queue)?
From what is written in documentation you might update return type to match your class like
public final class MyLambdaFunction implements RequestHandler<SQSEvent, MyClass> {
#Override
public MyClass handleRequest(SQSEvent event, Context context) {
MyClass myClassInstance = new MyClass();
return myClassInstance;
}
}
This is due to RequestHandler being a lambda and being able to answer to Http requests (and returning complex objects simplifies development).
However, to automatically send to another SQS queue you might use SQS sdk in your lambda to publish in another one before returning myClassInstance.
Keep in mind that RequestHandler is generic to handle any usecase not only SQSEvent

Clean code for removing switch condition(using polymorphism)

As SOLID principles say, it's better to remove switch conditions by converting them to classes and interfaces.
I want to do it with this code:
Note: This code is not real code and I just put my idea into it.
MessageModel message = getMessageFromAnAPI();
manageMessage(message);
...
void manageMessage(MessageModel message){
switch(message.typeId) {
case 1: justSave(message); break;
case 2: notifyAll(message); break;
case 3: notify(message); break;
}
}
Now I want to remove switch statement. So I create some classes for it and I try to implement a polymorphism here:
interface Message{
void manageMessage(MessageModel message);
}
class StorableMessage implements Message{
#Override
public void manageMessage(MessageModel message) {
justSave(message);
}
}
class PublicMessage implements Message{
#Override
public void manageMessage(MessageModel message) {
notifyAll(message);
}
}
class PrivateMessage implements Message{
#Override
public void manageMessage(MessageModel message) {
notify(message);
}
}
and then I call my API to get my MessageModel:
MessageModel message = getMessageFromAnAPI();
Now my problem is here. I have my model and I want manage it using my classes. As SOLID examples, I should do something like this:
PublicMessage message = new Message();
message.manageMessage(message);
But how can I know which type is related to this message to make an instance from it(PublicMessage or StorableMessage or PrivateMessage)?! Should I put switch block here again to do it or what?
You can do this:
static final Map<Integer,Consumer<MessageModel>> handlers = new HashMap<>();
static {
handlers.put(1, m -> justSave(m));
handlers.put(2, m -> notifyAll(m));
handlers.put(3, m -> notify(m));
}
This will remove your switch to
Consumer<Message> consumer = handlers.get(message.typeId);
if (consumer != null) { consumer.accept(message); }
Integration Operation Segregation Principle
You should of course encapsulate this:
class MessageHandlingService implements Consumer<MessageModel> {
static final Map<Integer,Consumer<MessageModel>> handlers = new HashMap<>();
static {
handlers.put(1, m -> justSave(m));
handlers.put(2, m -> notifyAll(m));
handlers.put(3, m -> notify(m));
}
public void accept(MessageModel message) {
Consumer<Message> consumer = handlers.getOrDefault(message.typeId,
m -> throw new MessageNotSupportedException());
consumer.accept(message);
}
}
with your client code
message = getMessageFromApi();
messageHandlingService.accept(message);
This service is the "integration" part (as opposed to the "implementation": cfg Integration Operation Segregation Principle).
With a CDI framework
For a production environment with a CDI framework, this would look something like this:
interface MessageHandler extends Consumer<MessageModel> {}
#Component
class MessageHandlingService implements MessageHandler {
Map<Integer,MessageHandler> handlers = new ConcurrentHashMap<>();
#Autowired
private SavingService saveService;
#Autowired
private NotificationService notificationService;
#PostConstruct
public void init() {
handlers.put(1, saveService::save);
handlers.put(2, notificationService::notifyAll);
handlers.put(3, notificationService::notify);
}
public void accept(MessageModel m) { // as above }
}
Behavior can be changed at Runtime
One of the advantages of this vs the switch in #user7's answer is that the behavior can be adjusted at runtime. You can imagine methods like
public MessageHandler setMessageHandler(Integer id, MessageHandler newHandler);
which would install the given MessageHandler and return the old one; this would allow you to add Decorators, for example.
An example for this being useful is if you have an unreliable web service supplying the handling; if it is accessible, it can be installed as a handlelr; otherwise, a default handler is used.
You can use a factory in this case to get the instance of Message. The factory would have all instances of Message and returns the appropriate one based on the MessageModel's typeId.
class MessageFactory {
private StorableMessage storableMessage;
private PrivateMessage privateMessage;
private PublicMessage publicMessage;
//You can either create the above using new operator or inject it using some Dependency injection framework.
public getMessage(MessageModel message) {
switch(message.typeId) {
case 1: return storableMessage;
case 2: return publicMessage;
case 3: return privateMessage
default: //Handle appropriately
}
}
}
The calling code would look like
MessageFactory messageFactory; //Injected
...
MessageModel messageModel = getMessageFromAnAPI();
Message message = messageFactory.getMessage(messageModel);
message.manageMessage(messageModel);
As you can see, this did not get rid of the switch entirely (and you need not as using switch is not bad in itself). What SOLID tries to say is to keep your code clean by following SRP (Single Responsibility Principle) and OCP (Open-Closed Principle) here. What it means here is that you code shouldn't have the actual processing logic to handle for each typeId in one place.
With the factory, you have moved the creation logic to a separate place and you have already moved the actual processing logic to respective classes.
EDIT:
Just to reiterate - My answer focuses on the SOLID aspect of the OP. By having separate handler classes (an instance of Message from the OP) you achieve the SRP. If one of the handler classes changes, or when you add a new message typeId (message.typeId) (i.e, add a new Message implementation) you need not modify the original and hence you achieve OCP. (On assumption that each of these does not contain trivial code). These are already done in the OP.
The real point of my answer here is to use a Factory to get a Message. The idea is to keep the main application code clean and limit the usages of switches, if/else and new operators to instantiation code. (Similar to #Configuration classes/ the classes that instantiate Beans when using Spring or Abstract modules in Guice). The OO principles do not say using switches are bad. It depends on where you use it. Using it in the application code does violate the SOLID principles and that is what I wanted to bring out.
I also like the idea from daniu# to use a functional way and the same can even be used in the above factory code (or can even use a simple Map to get rid of the switch).
The main point here is that you separate instantiation and configuration from execution.
Even with OOP we cannot avoid to distinguish between different cases using if/else cascades or switch statements. After all we have to create instances of specialized concrete classes.
But this should be in initialization code or some kind of factory.
Within the business logic we want to avoid if/else cascades or switch statements by calling generic methods on interfaces where the implementer know better themselves how to behave.
The usual clean code approach is for the MessageModel to contain its behavior.
interface Message {
void manage();
}
abstract class MessageModel implements Message {
}
public class StoringMessage extends MessageModel {
public void manage() {
store();
}
}
public class NotifyingMessage extends MessageModel {
public void manage() {
notify();
}
}
Your getMessageFromApi then returns the proper type, and your switch is
MessageModel model = getMessageFromApi();
model.manage();
This way, you essentially have the switch in the getMessageFromApi() method because it has to decide which message to generate.
However, that is fine because it does fill the message type id anyway; and the client code (where your switch currently resides) is resistent to changes to the messages; ie adding another message type will be be handled correctly.
The real problem you have is that MessageModel isn't polymorphic. You need to convert the MessageModels to a polymorphic Message class, but you shouldn't put any of the logic of what to do with the messages in this class. Instead, it should contain the actual contents of the message, and use the visitor pattern, as shown in Eric's Answer, so that other classes can operate on a Message. You don't need to use an anonymous Visitor; you can create implementing classes like a MessageActionVisitor.
To convert MessageModels to various Messages, you can use a factory, as shown in user7's answer. In addition to selecting which type of Message to return, the factory should fill in the fields of each type of Message using the MessageModel.
You can use the Factory Pattern. I would add an enum which has the values:
public enum MessageFacotry{
STORING(StoringMessage.TYPE, StoringMessage.class),
PUBLIC_MESSAGE(PublicMessage.TYPE, PublicMessage.class),
PRIVATE_MESSAGE(PrivateMessage.TYPE, PrivateMessage.class);
Class<? extends Message> clazz;
int type;
private MessageFactory(int type, Class<? extends Message> clazz){
this.clazz = clazz;
this.type = type;
}
public static Message getMessageByType(int type){
for(MessageFactory mf : values()){
if(mf.type == type){
return mf.clazz.newInstance();
}
}
throw new ..
}
}
Then you can call the static method of that enum and create an instance of the Message you want to manage.
You can use the Factory pattern and Visitor pattern together.
you can create a factory like this:
class MessageFactory {
public Message getMessage(MessageModel message) {
switch(message.typeId) {
case 1: return new StorableMessage((MessageModelType1) message);
case 2: return new PrivateMessage((MessageModelType2) message);
case 3: return new PublicMessage((MessageModelType3) message);
default: throw new IllegalArgumentException("unhandled message type");
}
}
}
and declare your messages like this:
interface Message {
void accept(Visitor visitor);
}
class StorableMessage implements Message {
private final MessageType1 message;
public StorableMessage(MessageModelType1 message) {
this.message = message;
}
#Override
public <Result> Result accept(Visitor<Result> visitor) {
return visitor.visit(this);
}
public MessageModelType1 getMessage() {
return message;
}
}
class PublicMessage implements Message {
...
}
class PrivateMessage implements Message {
...
}
and declare a Visitor like this:
interface Visitor {
void visit(StorableMessage message);
void visit(PublicMessage message);
void visit(PrivateMessage message);
}
and replace your switch statements with this:
Message message = ....;
message.accept(new Visitor() {
#Override
public void visit(StorableMessage message) {
justSave(message.getMessage());
}
#Override
public void visit(PublicMessage message) {
notifyAll(message.getMessage());
}
#Override
public void visit(PrivateMessage message) {
notify(message.getMessage());
}
});
If you want, instead of writing an anonymous class, you can create a class MessageModelFactory that has a private Visitor, and use that instead. in that case, it might be better to make the Visitor interface like this:
interface Visitor<Result> {
Result visit(StorableMessage message);
Result visit(PublicMessage message);
Result visit(PrivateMessage message);
}

Async task using generics for different return types from doInBackground

I have a utility class that extends Async task. I will be using this call to make HTTP requests in the background but I will also have more specialized sub classes of this that prepare the parameters, headers, url to call, so I can remove more common work from the GUI.
The issue is that I want to make use of Generics. The base API class doInBackground will return a string, there's a more specialized Json subclass that will call parent and return a JSONObject and do some parsing of the json response, there's specialized classes that extend the Json subclass and return List of custom objects, and so on. The reason for this is if we need to swap in XML and XML processing the specialized sub classes will have both a JSON and XML implementation. This is because we are re-using for a couple different api's overall.
So I tried playing around with Generics but I'm not 100% sure I understand the implementation in this case. It's obvious when you want to do things like List and make a list of List but how do I apply it here? I think I'm mainly confused about mocking up the code vs implementation, will everything just be T in the base and subclasses, than when I instantiate instances somewhere else like in the GUI that's when I specify the type of return I expect? Than I think I understand. So what I'm saying is when writing up the classes I only use T, never specify a Type and in the code where I instantiate instances that's when I specify a type and that's what the return type of doInBackground will be?
I also want to be able to implement onPostExecute() generically because I will use a callback setup so the GUI can easily subscribe to when the call is finished and process the result, but the interfact will also have a generic for the onPostExecute(T response). So I can create new instances, pass 'this', and when the async task is finished it will call the callback with the result and the callback can handle the appropriate type.
public class Base<T> extends AsyncTask<String, Integer, T>
{
protected Callback callback = null; //interface implemented for processing response
public Base setCallback(Callback callback){ this.callback = callback; return this; }
#Override
protected T doInBackground(String... uri)
{
//do http call
String response = "";
return response; //raw string of server response
}
#Override
final protected void onPostExecute(T result)
{
//no overrides, same every time
if( callback != null )
{
callback.finished(result); //forward generic result, but there it will be typed
}
}
public class JsonBase<T> extends Base<T>
{
#Override
protected T doInBackground(String... uri)
{
//this will be a JSONObject returned
String result = (String)super.dpInBackground(uri); //gives me back a string
return new JSONObject(result); //return a json object
}
}
public class SpecializedBase<T> extends JsonBase<T>
{
#Override
protected T doInBackground(String... uri)
{
//this will be a List<String> returned
//iterate over all json array strings and pass back
return new List<String>();
}
}
class FragmentFoo extends Fragment implements Callback
{
#Override
protected void onViewCreate(...)
{
//Example usage
new JsonBase< JSONObject >().setCallback(this).execute("<url">);
new SpecializedBase< List<String> >().setCallback(this).execute(""); //hard coded internally for example
}
//Can we do something like this?
#Override
protected void finished(JSONObject object)
{
//handle json response
}
#Override
protected void finished(List<String> strings)
{
//handle list of strings response
}
}
interface Callback
{
public <T> void finish(T response);
}
The specialized sub classes of Async will be tailored to specific types, and return different types, and we want to handle those specialized type depending on where we are in the GUI and what we're doing. Otherwise all we can do is all the logic in the GUI or have another middle layer of wrappers...This is all just a primitive example illustrating my point and how we want this to work.
Just kept T and anytime it complained about casting (T)response I just added a suppress warning. As long as I know what to expect in the specific callback and cast to that type, it's fine. But could easily crash at runtime if I make a mistake and cast it to something else.
It compiles, runs, and works. But doesn't seem like a clean appropriate solution.
I know this is an old question but I've just come across it - used most of your solution and improved it a little to solve the issue you had.
I'll just paste the code, but basically just type the list but rather than using it as a return value I use an integer static for the return value in the callback and create the list as a field of the asynctask object itself which is then accessed in the callback method. (I also use a DatabaseLoaderParams for clarity)
public class DatabaseLoader<T> extends AsyncTask<DatabaseLoaderParams, Void, Integer> {
ArrayList<T> returnList;
protected DbLoaderCallback callback = null; //interface implemented for processing response
public DatabaseLoader setCallback(DbLoaderCallback callback){ this.callback = callback; return this; }
#Override
protected Integer doInBackground(DatabaseLoaderParams... params) {
//you have to give the object class to the asynctask
ArrayList<T> mReturnList = getList(params[0].objectClass);
try {
// DB loading code
} catch (Exception e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
return 0;
}
// Done!
returnList=mReturnList;
return params[0].startId;
}
#Override
final protected void onPostExecute(Integer startId)
{
if( callback != null && startId>0)
{
callback.onLoadFinished(startId); //forward generic result, but there it will be typed
}
}
private <T> ArrayList<T> getList(Class<T> requiredType) {
return new ArrayList<T>();
}
In the activity:
#Override
public void onLoadFinished(int startId)
{
switch(startId){
case INTEGER_STATIC:
//check the type if you want but I don't bother
for(DBObject dbObject : DBLoader.returnList){
....

Handling of <?> type in Java generics

Let's say I have an interface that describes possible request handlers that can service actions requested by a client in the context of some client session state, that is stored by the client:
public interface RequestHandler<State> {
// Perform action in the context of currentState and return updated state
public State request(State currentState, String action);
}
To make it easy to implement the RequestHandlers, I added the generic type State, which encapsulates all the required client session data.
Now, a simple client could look like this:
public class Client {
private final RequestHandler<?> handler;
private Object state;
Client(RequestHandler<?> handler) {
// Initialize the RequestHandler to use for "go"-requests
this.handler = handler;
// Initialize our client state to "null"
this.state = null;
}
public void go() {
// Execute "go"-request in current state and update state
state = handler.request(state, "go"); // <= this is an error (see below)
}
}
During creation it gets provided with a RequestHandler, which it then later uses to execute "go"-requests. It also manages storage of its current session state in the private state variable.
Now, since my clients shouldn't need to worry about what the session state actually looks like internally, I would like to use RequestHandler<?> as shown. But, unfortunately, this gives me an error in the state = handler.request... line:
The method request(capture#3-of ?, String) in the type
RequestHandler is not applicable for the arguments
(Object, String)
Is there an issue with just changing the offending line to:
state = ((RequestHandler<Object>) handler).request(state, "go");
(which turns the error into an "Unchecked cast"-warning)
Clearly, this way I loose type-checking on my state-object, but if the Client only ever sets it to null or something returned by the RequestHandler, there should be no problems, right?
I know I could also just parameterize Client as Client<State> as well and then using State in place of Object and ? everywhere. But I would rather like to avoid this, since it's (in my opinion) just dead weight in this case that will have to be carried around wherever a Client is instantiated or used...
There is no way to cast state to (?), right?
UPDATE:
There's a beautiful solution to this problem if everything was happening inside a single method rather than a class:
public <State> void go(RequestHandler<State> handler) {
State state = null;
state = handler.request(state, "go");
state = handler.request(state, "go again");
state = handler.request(state, "go one more time");
}
This, I can call anywhere without having to always specify what State actually is. But there is no equivalent construct for entire classes (some inferred generic argument) is there?
It seems like it would be okay to make Client generic, reflecting the type of the RequestHandler. But, if you want to hide that inside the client, you can do it like this:
public final class Client
{
private final CaptureHelper<?> helper;
<T> Client(RequestHandler<T> handler) {
this.helper = new CaptureHelper<T>(handler);
}
public void go()
{
helper.request("go");
}
private final class CaptureHelper<T>
{
private final RequestHandler<T> handler;
private T state;
private CaptureHelper(RequestHandler<T> handler) {
this.handler = handler;
}
private void request(String action)
{
state = handler.request(state, action);
}
}
}
Note that this frees anyone using a client from caring about the generic type of its RequestHandler. Users would have code like this:
RequestHandler<?> handler = ... ;
Client client = new Client(handler); /* Look ma, no generics! */
client.go();
It appears that your intention is that clients should be able to define RequestHandlers that consume and return a variety of objects conforming to a State interface. If so, you need to define your interface like this so that the clients can specify the particular State type they're using:
public interface RequestHandler<StateType> {
// Perform action in the context of currentState and return updated state
public StateType request(StateType currentState, String action);
}
If your Client class is intended to be generic (in the non-technical sense), then it should also be generic (in the technical sense) by allowing subclasses or its own clients to specify the type of the State object:
public class Client<StateType> {
private StateType state;
...
}
The problem with your existing code is that there's absolutely no information contained in an absolute wildcard. When the wildcard represents a return type, it might be the case that you're getting an object of class Object, with no useful behavior, and as an argument type, it would basically mean that the client could expect you to supply an object of any specific class but wasn't saying which.

How to Return Different Objects via Asynctask in Android

I figured this must be a common question, but I surprisingly couldn't find an answer, so maybe my entire structure is terribad...
I have an activity which downloads values/states of a game from a web service via AsyncTask. These values are used to update a custom view.
Once the view is created, various events from the view launch an AsyncTask to download other information.
This is functional, but the problem is I now have half a dozen AsyncTask classes in the activity with almost identical code. The only difference is the type of object that is returned (which is based on the json from the web service) and the method that is called from onPostExecute().
How can I use just two AsyncTask (one for post and one for get) without knowing what type of json object will be returned by the web service?
In a similar vein, how can I determine the type of object returned by the web service? The web service, if there is a problem, will return a json string that correlates to an ErrorMessage object rather than (for example) a GameData object.
Should I be using switch and instanceof in onPostExecute() somehow? Callbacks maybe?
You can use an abstract base class, which your related classes extends.
Sample code:
public abstract class IBaseObject {
protected String error;
public IBaseObject(String param) {
error = param;
}
public abstract String getError();
}
public class ObjectOne extends IBaseObject {
private String objectParam;
public ObjectOne(String error, String objectSpecificParam) {
super(error);
objectParam = objectSpecificParam;
}
#Override
public String getError() {
return error;
}
}
and for example, use it like this:
private class GetTask extends AsyncTask<String, Void, IBaseObject> {
protected IBaseObject doInBackground(String... url) {
// Get your data.
// Construct your corresponding object given by specific
// parameters from your JSON response.
if (a_parameter_match) {
return new ObjectOne(some_json_params...);
} else {
return new ObjectTwo(some_json_params...);
}
}
protected void onPostExecute(IBaseObject object) {
object.getError(); // Or whatever you need here.
}
}
This is just from the top of my head. I couldn't relate to your specific problem, although the ideas here should be enough to get you started on your new structure.
This is too long for a comment, so I'm writing an answer. However it was the advice of #Pompe de velo that got me on this track, so I am accepting that answer. I also left out some information from my question that could have been useful.
Anyway, as of right now I do not see any major downsides to this approach, but time ( or maybe another SO user ;] ) will tell...
Essentially I have assigned a constant to every type of object that the activity will try to get. The part that I left out was that the server only returns an error object on a 4xx-5xx http status code. In other words, I am certain to either get the object I am expecting or an error object and I can determine which I got from the status code. Then a switch sends the actual json string to the appropriate method that can manipulate the response as necessary.
Simplified pseudocode...
private void getGameData(){
new MyAsyncTask(this, MyAsyncTask.OBJ_GAME_DATA).execute();
}
static class MyAsyncTask extends AsyncTask<String, Integer, String> {
private int outputObjectType;
protected static final int OBJ_GAME_DATA = 0;
protected static final int OBJ_OTHER_DATA = 1;
protected static final int OBJ_DIFFERENT_DATA = 2;
protected static final int OBJ_SERVER_ERROR = 3;
MyAsyncTask(MyActivity activity, int expectedObject){
outputObjectType = expectedObject;
}
doInBackground(){
if(httpStatusCode >= 400){
outputObjectType = MyAsyncTask.OBJ_SERVER_ERROR;
}
return jsonStringFromServer;
}
onPostExecute(String json){
switch(outputObjectType){
case MyAsyncTask.OBJ_SERVER_ERROR:
serverError(json);
break;
case MyAsyncTask.OBJ_GAME_DATA:
processGameData(json);
break;
// ....
}
}
}
private void serverError(String json){
ServerError se = new Gson().fromJson(json, ServerError.class);
Log.d(TAG, se.getErrorMessage());
}
private void processGameData(String json){
GameData gd = new Gson().fromJson(json, GameData.class);
// .......
}
I think this is more less what #Pompe de velo was saying, however I am just making my a_parameter_match based on the status code rather than something within the json.
If this is flawed, I'd love to learn why !

Categories

Resources