Package com.collective2.signalEntry.implementation

Source Code of com.collective2.signalEntry.implementation.Request

/**
* This notice shall not be removed.
* See the "LICENSE.txt" file found in the root folder
* for the full license governing this code.
* Nathan Tippy   7/21/12
*/
package com.collective2.signalEntry.implementation;

import com.collective2.signalEntry.C2ServiceException;
import com.collective2.signalEntry.Duration;
import com.collective2.signalEntry.Parameter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.EnumMap;
import java.util.Map;

public class Request extends EnumMap<Parameter, Object> {

    private static final Logger  logger      = LoggerFactory.getLogger(Request.class);
    private static final String  urlProtocol = "http";
    private static final int     urlPort     = -1;
    private static final String  urlHost     = "www.collective2.com";
    private static final String  urlFile     = "/cgi-perl/signal.mpl";

    //Any existing pending request must be approved again.  Once its sent in the journal it will be either
    //marked as rejected or sent.  Until then approval will need to be given again if the servers are down
    //and the sender has saved the requests and sender has restarted.  In this case due to the stale nature of
    //the signals it is likely the human will want to cancel all the requests so it was decided to ask again
    //rather than persist the approvals.
    private transient Boolean approved;//tri-state null is 'unknown' and will require user input

    public Request(Command command) {
        super((Parameter.class));
        super.put(Parameter.SignalEntryCommand, command);
        if (!command.approvalRequired()) {
            approved = true;
        }
    }

    public Command command() {
        return (Command) get(Parameter.SignalEntryCommand);
    }

    public void setApproved(boolean approved) {
        assert(this.approved == null) : "Should not set approval once it is already set, this is not a good idea.";
        this.approved = approved;
    }

    public boolean isApprovalKnown() {
        return null != approved;
    }

    public Boolean isApproved() {
        return approved;
    }

    @Override
    public Object put(Parameter parameter, Object value) {

        if (Parameter.Password != parameter) {

            if (super.containsKey(parameter)) {
                throw new UnsupportedOperationException("Can not modify "+parameter+" with new value "+value+" already set to "+super.get(parameter));
            }

            command().validateApplicable(this, parameter);
            parameter.validateValue(value);
        }
        return super.put(parameter, value);
    }

    public Request secureClone() {
        Request clone = (Request) super.clone();
        if (clone.containsKey(Parameter.Password)) {
            clone.put(Parameter.Password,"*****");
        }
        clone.approved = this.approved;
        return clone;
    }

    public Request baseConditional() {
        //only fields needed for building all-in-one dependent signals
       Request base = new Request(command());
       Parameter[] copy = new Parameter[]{
               Parameter.Instrument,
               Parameter.Symbol,
               Parameter.Password,
               Parameter.SystemId
       };

       base.put(Parameter.TimeInForce, Duration.GoodTilCancel);//this is conditional upon another
       //if the dependent is cancelled this one will also be cancelled but not until then

       for(Parameter p:copy) {
           Object obj = get(p);
           if (obj!=null) {
                base.put(p,obj);
           }
       }
       base.approved = this.approved;
       return base;
    }

    public String toString() {
        return buildURL(this, true).toString();
    }

    public String humanString() {
        StringBuilder builder = new StringBuilder();

        builder.append(command().name());

        for(Entry<Parameter,Object> entry:entrySet()) {
            //do not print command that one has already been done
            if (entry.getKey() != Parameter.SignalEntryCommand) {
                builder.append(' ').append(entry.getKey().name()).append(':').append(entry.getValue().toString());
            }
        }
        return builder.toString();
    }

    public static Request parseURL(String url) {

        String[] split = url.split("\\?|&");
        if (split.length<=0 || !split[0].endsWith("signal.mpl")) {
            throw new C2ServiceException("Can not parse url base "+url,false);
        }
        //pull out the command from index 1
        Command command = null;
        if (split[1].startsWith("cmd=")) {
            command = (Command)Parameter.SignalEntryCommand.parse(split[1].substring(4));
         } else {
            throw new C2ServiceException("Can not parse out command "+url,false);
        }


        //all the fields start at 2
        Request request = new Request(command);

        //do not process zero or one
        int i = split.length;
        while(--i>1) {
            String[] arg = split[i].split("=");
            String endsWith = arg[0]+'=';

            Parameter found = lookupParameter(endsWith);
            Object value = found.parse(arg[1]);
            request.put(found,value);
        }

        return request;
    }

    private static Parameter lookupParameter(String endsWith) {
        Parameter found = null;
        for(Parameter p:Parameter.values()) {
            if (p.key().endsWith(endsWith)) {
                found = p;
                break;
            }
        }
        return found;
    }

    public URL buildURL() {
        return buildURL(this, false);
    }

    private URL buildURL(Map<Parameter, Object> activeMap, boolean hidePassword) {
        StringBuilder urlFileQuery = new StringBuilder(1024);
        urlFileQuery.append(urlFile);

        for (Parameter p : activeMap.keySet()) {
            if (Parameter.Password == p && hidePassword) {
                urlFileQuery.append(p.key()).append("PASSWORD");
            } else {
                urlFileQuery.append(p.key());
                if (p.shouldEncode()) {
                    try {
                        urlFileQuery.append(encode(activeMap.get(p)));
                    } catch (UnsupportedEncodingException e) {
                        // should never happen
                        String msg = "UTF-8 is not supported on this platform?";
                        logger.error(msg, e);
                        throw new C2ServiceException(msg, e, false);
                    }
                } else {
                    urlFileQuery.append(activeMap.get(p));
                }
            }
        }

        try {
            return new URL(urlProtocol, urlHost, urlPort, urlFileQuery.toString(), null);
        } catch (MalformedURLException e) {
            throw new C2ServiceException(e, false);
        }
    }

    protected String encode(Object value) throws UnsupportedEncodingException {
        return URLEncoder.encode(value.toString(), "UTF-8");
    }

    @Override
    public Object remove(Object key) {
        throw new UnsupportedOperationException("Element removal is not supported because it will break equivalence.");
    }

    public boolean validate() {
        command().validate(this);
        return true;
    }



}
TOP

Related Classes of com.collective2.signalEntry.implementation.Request

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.