3
\$\begingroup\$

My task is to write a program to store files in object store. One of the subtasks requires to send json or xml format response to the file uploader/downloader as requested by client.

The following rules must be followed:

                         entry                         
               +-------------------------+             
               v                         v             
           upload                      download        
       +-----------+              +--------------+     
       v           v              v              v     
    succ          err            succ           err    
  +-----+       +-----+                       +-----+  
  v     v       v     v                       v     v  
json1  xml1    json2  xml2                  josn2  xml2
  1. if user uploads file with success, return json/xml type 1
  2. if user uploads file with error, return json/xml type 2
  3. if user downloads file with success, don't change return object
  4. if user downloads file with error, return json/xml type 2

I've managed to solve the task but I'm not satisfied with the class dependencies and nested if/else-s I have. I think mixture of abstract factory and strategy are suitable for the issue. Can you give me a hint on how I can deal with the problem?

My code snippet:

public Result upload(HttpServletRequest request) {
        UploadRequestParams uploadParams = UploadRequestParams.getObjectFrom(request);
        ... // create info object
        Result res = handleUploadRequest(uploadParams);

        Result result = jsonXml(info, res);
        return result;
    }

private Result jsonXml(RequestInfo info, Result result) {
        Serializer ser;
        if ("xml".equals(format)) {
            ser = new XmlSerializer();
        } else {
            ser = new JsonSerializer();
        }
        Result res = ser.serialize(info, result);

        return res;
    }

@Override
public Result serialize(RequestInfo info, Result result) { // json implementation
        GsonBuilder builder = new GsonBuilder();
        Gson g = builder.create();

        InputStream stream = null;
        InfoInterface wrap; 
        if (info.isUpload()) {
            if (result.isValid()) {
                wrap = new InfoWrapperImpl1(info, result);
            } else {
                wrap = new InfoWrapperImpl2(info, result);
            }
        } else {
            wrap = new InfoWrapperImpl1(info, result);
        }
        String res = g.toJson(wrap);
        stream = new ByteArrayInputStream(res.getBytes(StandardCharsets.UTF_8));
        Result newRes = Result.getBuilder().setInputStream(stream).setResultCode(result.getResultCode()).build();
        return newRes;
    }

private class InfoWrapperImpl1 implements InfoInterface {
        private String fileName;
        private ResultCode code;

        public InfoWrapper1(RequestInfo info, Result res) {
            this.fileName = info.getUniqueName();
            this.code = res.getCode;
        }
    }

UML class diagram:

ugly

EDIT

I rewrote serialize method, but looks like to be bound to the parameters' implementation. Am I right? On the other, I got rid of the ugly nested classes.

@Override
    public Result serialize(RequestInfo info, Result result) {

        JsonObject body = new JsonObject();

        JsonObject resultCode = new JsonObject();
        resultCode.addProperty("code", result.getResultCode().getCode());
        resultCode.addProperty("value", result.getResultCode().getDescription());

        if (info.isUploadRequest() && result.isValid()) {
            body.addProperty(fileTag, info.getExtendedName());
            body.addProperty("checksum", result.getMySwiftObject().getEtag());
        }
        body.add(statusTag, resultCode);

        String jsonRes = body.toString();
        InputStream stream = new ByteArrayInputStream(jsonRes.getBytes(StandardCharsets.UTF_8));
        return Result.getBuilder().setInputStream(stream).setResultCode(result.getResultCode()).build();
    }
\$\endgroup\$
3
\$\begingroup\$
   if (info.isUpload()) {
        if (result.isValid()) {
            wrap = new InfoWrapperImpl1(info, result);
        } else {
            wrap = new InfoWrapperImpl2(info, result);
        }
    } else {
        wrap = new InfoWrapperImpl1(info, result);
    }

Can be written as:

   if (!info.isUpload() || result.isValid()) {
        wrap = new InfoWrapperImpl1(info, result);
    } else {
        wrap = new InfoWrapperImpl2(info, result);
    }

Also InfoWrapperImpl1 and InfoWrapperImpl2 are not very good names, as they are not expressive and look quite similar to each other.

\$\endgroup\$
  • \$\begingroup\$ good pint. How can we move isUpload isValid logic from the serializer class? \$\endgroup\$ – gkiko Feb 25 '15 at 11:53
  • \$\begingroup\$ I mean this json class mustn't decide how to act. It must be constructed in a way that outputs desirable result, don't you think? \$\endgroup\$ – gkiko Feb 25 '15 at 12:00
  • \$\begingroup\$ @gkiko honestly, I'm not too sure what your current structure is exactly. It would be helpful if you could add a bit more context (and ideally a uml diagram, if you have one). \$\endgroup\$ – tim Feb 25 '15 at 12:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.