io.personium.core.rs.cell.MessageODataResource.java Source code

Java tutorial

Introduction

Here is the source code for io.personium.core.rs.cell.MessageODataResource.java

Source

/**
 * personium.io
 * Copyright 2014 FUJITSU LIMITED
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.personium.core.rs.cell;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.UriInfo;

import org.apache.commons.lang.CharEncoding;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.odata4j.core.OCollection;
import org.odata4j.core.OCollections;
import org.odata4j.core.OComplexObjects;
import org.odata4j.core.ODataConstants;
import org.odata4j.core.ODataVersion;
import org.odata4j.core.OEntity;
import org.odata4j.core.OEntityKey;
import org.odata4j.core.OObject;
import org.odata4j.core.OProperties;
import org.odata4j.core.OProperty;
import org.odata4j.edm.EdmCollectionType;
import org.odata4j.edm.EdmComplexType;
import org.odata4j.edm.EdmEntitySet;
import org.odata4j.producer.EntitiesResponse;
import org.odata4j.producer.EntityResponse;
import org.odata4j.producer.InlineCount;
import org.odata4j.producer.QueryInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.personium.common.auth.token.Role;
import io.personium.common.auth.token.TransCellAccessToken;
import io.personium.common.utils.PersoniumCoreUtils;
import io.personium.core.PersoniumCoreException;
import io.personium.core.auth.OAuth2Helper;
import io.personium.core.model.Box;
import io.personium.core.model.ctl.Common;
import io.personium.core.model.ctl.CtlSchema;
import io.personium.core.model.ctl.ExtCell;
import io.personium.core.model.ctl.ReceivedMessage;
import io.personium.core.model.ctl.ReceivedMessagePort;
import io.personium.core.model.ctl.Relation;
import io.personium.core.model.ctl.SentMessage;
import io.personium.core.model.ctl.SentMessagePort;
import io.personium.core.model.impl.es.odata.CellCtlODataProducer;
import io.personium.core.odata.OEntityWrapper;
import io.personium.core.odata.PersoniumODataProducer;
import io.personium.core.rs.odata.AbstractODataResource;
import io.personium.core.rs.odata.ODataResource;
import io.personium.core.utils.HttpClientFactory;
import io.personium.core.utils.ODataUtils;
import io.personium.core.utils.ResourceUtils;

/**
 * __message?OData?.
 */
public final class MessageODataResource extends AbstractODataResource {

    static Logger log = LoggerFactory.getLogger(MessageODataResource.class);

    private MessageResource odataResource;
    private Map<String, String> propMap = new HashMap<String, String>();
    private String version;

    /** ??. */
    private static final int MAX_SENT_NUM = 1000;

    /**
     * constructor.
     * @param odataResource OData
     * @param producer OData
     * @param entityTypeName ??
     */
    public MessageODataResource(MessageResource odataResource, PersoniumODataProducer producer,
            String entityTypeName) {
        this.odataResource = odataResource;
        setOdataProducer(producer);
        setEntitySetName(entityTypeName);
    }

    /**
     * personium Version?.
     * @param version ? version
     */
    public void setVersion(String version) {
        this.version = version;
    }

    /**
     * ???Entity??.
     * @param uriInfo URL
     * @param reader 
     * @return response
     */
    protected Response createMessage(UriInfo uriInfo, Reader reader) {

        // responseURL?__ctl?
        UriInfo resUriInfo = PersoniumCoreUtils.createUriInfo(uriInfo, 2, "__ctl");

        // Entity?? Producer??
        OEntityWrapper oew = getOEntityWrapper(reader, odataResource,
                CtlSchema.getEdmDataServicesForMessage().build());
        EntityResponse res = getOdataProducer().createEntity(getEntitySetName(), oew);

        // ???
        OEntity ent = res.getEntity();
        MediaType outputFormat = MediaType.APPLICATION_JSON_TYPE;
        List<MediaType> contentTypes = new ArrayList<MediaType>();
        contentTypes.add(MediaType.APPLICATION_JSON_TYPE);
        String key = AbstractODataResource.replaceDummyKeyToNull(ent.getEntityKey().toKeyString());
        String responseStr = renderEntityResponse(resUriInfo, res, "json", contentTypes);

        // ??
        responseStr = escapeResponsebody(responseStr);

        ResponseBuilder rb = getPostResponseBuilder(ent, outputFormat, responseStr, resUriInfo, key);
        return rb.build();
    }

    /**
     * ??.
     * @param reader 
     * @param key Id
     * @return response
     */
    protected Response changeMessageStatus(Reader reader, String key) {

        JSONObject body;
        try {
            body = ResourceUtils.parseBodyAsJSON(reader);
        } catch (IOException e1) {
            throw PersoniumCoreException.OData.JSON_PARSE_ERROR.reason(e1);
        } catch (ParseException e1) {
            throw PersoniumCoreException.OData.JSON_PARSE_ERROR.reason(e1);
        }

        String status = (String) body.get(ReceivedMessage.MESSAGE_COMMAND);
        // ??
        if (!ReceivedMessage.STATUS_UNREAD.equals(status) && !ReceivedMessage.STATUS_READ.equals(status)
                && !ReceivedMessage.STATUS_APPROVED.equals(status)
                && !ReceivedMessage.STATUS_REJECTED.equals(status)) {
            throw PersoniumCoreException.OData.REQUEST_FIELD_FORMAT_ERROR.params(ReceivedMessage.MESSAGE_COMMAND);
        }

        // EdmEntitySet??
        EdmEntitySet edmEntitySet = getOdataProducer().getMetadata()
                .getEdmEntitySet(ReceivedMessagePort.EDM_TYPE_NAME);

        // OEntityKey??
        OEntityKey oEntityKey;
        try {
            oEntityKey = OEntityKey.parse("('" + key + "')");
        } catch (IllegalArgumentException e) {
            throw PersoniumCoreException.OData.ENTITY_KEY_PARSE_ERROR.reason(e);
        }

        // ???/Producer??
        String etag = ((CellCtlODataProducer) getOdataProducer()).changeStatusAndUpdateRelation(edmEntitySet,
                oEntityKey, status);

        return Response.noContent().header(HttpHeaders.ETAG, ODataResource.renderEtagHeader(etag))
                .header(ODataConstants.Headers.DATA_SERVICE_VERSION, ODataVersion.V2.asString).build();
    }

    /**
     * ?.
     * @param props 
     * @param id ?ID
     */
    @Override
    protected void editProperty(List<OProperty<?>> props, String id) {

        if (ReceivedMessage.EDM_TYPE_NAME.equals(this.getEntitySetName())) {
            for (int i = 0; i < props.size(); i++) {
                if (ReceivedMessagePort.P_SCHEMA.getName().equals(props.get(i).getName())) {
                    String schema = (String) props.get(i).getValue();
                    Box box = this.odataResource.getAccessContext().getCell().getBoxForSchema(schema);
                    String boxName = box != null ? box.getName() : null; // CHECKSTYLE IGNORE - To eliminate useless code
                    // ??Schema?????????????
                    props.remove(i);
                    for (int j = 0; j < props.size(); j++) {
                        if (ReceivedMessagePort.P_BOX_NAME.getName().equals(props.get(j).getName())) {
                            // Replace with BoxName obtained from schema
                            props.set(j, OProperties.string(ReceivedMessagePort.P_BOX_NAME.getName(), boxName));
                            break;
                        }
                    }
                    break;
                }
            }
        } else if (SentMessage.EDM_TYPE_NAME.equals(this.getEntitySetName())) {

            EdmCollectionType collectionType = new EdmCollectionType(SentMessage.P_RESULT.getCollectionKind(),
                    SentMessage.P_RESULT.getType());

            // ?API????????Results?
            OCollection.Builder<OObject> builder = requestReceivedMessage(collectionType, id);

            // ComplexType?????
            props.add(OProperties.collection(SentMessage.P_RESULT.getName(), collectionType, builder.build()));

            for (int i = 0; i < props.size(); i++) {
                if (SentMessagePort.P_BOX_BOUND.getName().equals(props.get(i).getName())) {
                    // ??BoxBound?????????????
                    props.remove(i);
                } else if (SentMessagePort.P_BOX_NAME.getName().equals(props.get(i).getName())) {
                    String schema = this.odataResource.getAccessContext().getSchema();
                    Box box = this.odataResource.getAccessContext().getCell().getBoxForSchema(schema);
                    String boxName = box != null ? box.getName() : null; // CHECKSTYLE IGNORE - To eliminate useless code
                    // Replace with BoxName obtained from schema
                    props.set(i, OProperties.string(SentMessagePort.P_BOX_NAME.getName(), boxName));
                } else if (SentMessagePort.P_RESULT.getName().equals(props.get(i).getName())) {
                    // ??Result???????????????
                    props.set(i, OProperties.collection(SentMessage.P_RESULT.getName(), collectionType,
                            builder.build()));
                }
            }

        }

    }

    /**
     * ?API?.
     * @param collectionType EdmCollectionType
     * @param idKey ??ID
     * @return ???
     */
    private OCollection.Builder<OObject> requestReceivedMessage(final EdmCollectionType collectionType,
            String idKey) {

        OCollection.Builder<OObject> builder = OCollections.<OObject>newBuilder(collectionType.getItemType());
        // ComplexType???
        EdmComplexType ct = SentMessage.COMPLEXTYPE_BUILDER.build();

        String fromCellUrl = this.odataResource.getAccessContext().getCell().getUrl();

        // ?
        List<String> toList = createRequestUrl();

        // ??
        for (String toCellUrl : toList) {
            List<OProperty<?>> result = null;
            toCellUrl = formatCellUrl(toCellUrl);

            // ?API???
            TransCellAccessToken token = new TransCellAccessToken(fromCellUrl, fromCellUrl, toCellUrl,
                    new ArrayList<Role>(), "");

            // ('ID')?ID???
            Pattern formatPattern = Pattern.compile("\\('(.+)'\\)");
            Matcher formatMatcher = formatPattern.matcher(idKey);
            formatMatcher.matches();
            String id = formatMatcher.group(1);
            // ?API???
            JSONObject requestBody = createRequestJsonBody(fromCellUrl, toCellUrl, toList, id);

            // ?API?
            result = requestHttpReceivedMessage(token, toCellUrl, requestBody);

            // ?????
            builder.add(OComplexObjects.create(ct, result));
        }

        return builder;
    }

    /**
     * ?.
     * @return ??CellURL?
     */
    private List<String> createRequestUrl() {
        List<String> toList = new ArrayList<String>();
        String requestToStr = null;
        String requestToRelationStr = null;

        requestToStr = this.propMap.get(SentMessage.P_TO.getName());
        requestToRelationStr = this.propMap.get(SentMessage.P_TO_RELATION.getName());

        // ?To?CellURL?
        if (requestToStr != null) {
            String[] uriList = requestToStr.split(",");
            for (String uri : uriList) {
                toList.add(uri);
            }
        }

        // ?ToRelation?CellURL??
        if (requestToRelationStr != null) {
            List<String> extCellUrlList = getExtCellListFromToRelation(requestToRelationStr);
            toList.addAll(extCellUrlList);
        }

        List<String> formatToList = new ArrayList<String>();
        // ?
        for (String to : toList) {
            // ?"/"
            if (!to.endsWith("/")) {
                to += "/";
            }
            // To?ToRelation?????????
            if (!formatToList.contains(to)) {
                formatToList.add(to);
            }
        }
        checkMaxDestinationsSize(formatToList.size());
        return formatToList;
    }

    /**
     * ToRelation???Relation???ExtCell?URL??.
     * @param toRelation ToRelation?
     * @return extCellUrlList ExtCell?URL
     */
    protected List<String> getExtCellListFromToRelation(String toRelation) {
        List<String> extCellUrlList = new ArrayList<String>();
        String keyString = AbstractODataResource.replaceNullToDummyKeyWithParenthesis("'" + toRelation + "'");
        OEntityKey oEntityKey = OEntityKey.parse(keyString);
        EntitiesResponse response = null;
        try {
            QueryInfo query = new QueryInfo(InlineCount.ALLPAGES, MAX_SENT_NUM, null, null, null, null, null, null,
                    null);
            response = (EntitiesResponse) getOdataProducer().getNavProperty(Relation.EDM_TYPE_NAME, oEntityKey,
                    "_" + ExtCell.EDM_TYPE_NAME, query);
        } catch (PersoniumCoreException e) {
            if (PersoniumCoreException.OData.NO_SUCH_ENTITY.getCode().equals(e.getCode())) {
                // ToRelation???Relation??????400?
                throw PersoniumCoreException.SentMessage.TO_RELATION_NOT_FOUND_ERROR.params(toRelation);
            } else {
                throw e;
            }
        }
        // ToRelation????ExtCell?URL?
        List<OEntity> extCellEntities = response.getEntities();
        checkMaxDestinationsSize(response.getInlineCount());
        for (OEntity extCell : extCellEntities) {
            extCellUrlList.add(extCell.getProperty(ExtCell.P_URL.getName()).getValue().toString());
        }
        if (extCellUrlList.isEmpty()) {
            // ToRelation???Relation????ExtCell??????400?
            throw PersoniumCoreException.SentMessage.RELATED_EXTCELL_NOT_FOUND_ERROR.params(toRelation);
        }
        return extCellUrlList;
    }

    /**
     * ?URL????????.
     * @param destinationsSize ?URL?
     */
    public void checkMaxDestinationsSize(int destinationsSize) {
        if (destinationsSize > MAX_SENT_NUM) {
            throw PersoniumCoreException.SentMessage.OVER_MAX_SENT_NUM;
        }
    }

    /**
     * ?API???.
     * @param fromCellUrl ?CellURL
     * @param targetCellUrl ?CellURL
     * @param toList 
     * @param id ??ID
     * @return 
     */
    @SuppressWarnings("unchecked")
    private JSONObject createRequestJsonBody(String fromCellUrl, String targetCellUrl, List<String> toList,
            String id) {
        JSONObject requestBody = new JSONObject();
        String type = this.propMap.get(SentMessage.P_TYPE.getName());
        boolean boxBound = Boolean.parseBoolean(this.propMap.get(SentMessagePort.P_BOX_BOUND.getName()));

        // Status?
        String status = null;
        if (ReceivedMessage.TYPE_MESSAGE.equals(type)) {
            status = ReceivedMessage.STATUS_UNREAD;
        } else {
            status = ReceivedMessage.STATUS_NONE;
        }

        // MulticastTo?
        String multicastTo = null;
        StringBuilder sbMulticastTo = null;
        for (String to : toList) {
            String formatTo = formatCellUrl(to);
            if (!formatTo.equals(targetCellUrl)) {
                if (sbMulticastTo == null) {
                    sbMulticastTo = new StringBuilder();
                } else {
                    sbMulticastTo.append(",");
                }
                sbMulticastTo.append(formatTo);
            }
        }
        if (sbMulticastTo != null) {
            multicastTo = sbMulticastTo.toString();
        }

        requestBody.put(ReceivedMessage.P_ID.getName(), id);
        if (boxBound) {
            requestBody.put(ReceivedMessagePort.P_SCHEMA.getName(),
                    this.odataResource.getAccessContext().getSchema());
        }
        requestBody.put(ReceivedMessage.P_IN_REPLY_TO.getName(),
                this.propMap.get(SentMessage.P_IN_REPLY_TO.getName()));
        requestBody.put(ReceivedMessage.P_FROM.getName(), fromCellUrl);
        requestBody.put(ReceivedMessage.P_MULTICAST_TO.getName(), multicastTo);
        requestBody.put(ReceivedMessage.P_TYPE.getName(), type);
        requestBody.put(ReceivedMessage.P_TITLE.getName(), this.propMap.get(SentMessage.P_TITLE.getName()));
        requestBody.put(ReceivedMessage.P_BODY.getName(), this.propMap.get(SentMessage.P_BODY.getName()));
        requestBody.put(ReceivedMessage.P_PRIORITY.getName(),
                Integer.valueOf(this.propMap.get(SentMessage.P_PRIORITY.getName())));
        requestBody.put(ReceivedMessage.P_STATUS.getName(), status);
        requestBody.put(ReceivedMessage.P_REQUEST_RELATION.getName(),
                this.propMap.get(SentMessage.P_REQUEST_RELATION.getName()));
        requestBody.put(ReceivedMessage.P_REQUEST_RELATION_TARGET.getName(),
                this.propMap.get(SentMessage.P_REQUEST_RELATION_TARGET.getName()));

        return requestBody;
    }

    /**
     * CellURL???.
     * @param cellUrl cell?Url
     * @return ?
     */
    private String formatCellUrl(String cellUrl) {
        String formatCellUrl = cellUrl;
        if (!cellUrl.endsWith("/")) {
            formatCellUrl += "/";
        }
        return formatCellUrl;
    }

    /**
     * ?API?.
     * @param token 
     * @param requestCellUrl CellURL
     * @param jsonBody 
     * @return ?
     */
    private List<OProperty<?>> requestHttpReceivedMessage(TransCellAccessToken token, String requestCellUrl,
            JSONObject jsonBody) {
        String requestUrl = requestCellUrl + "__message/port";

        // ???
        HttpClient client = HttpClientFactory.create(HttpClientFactory.TYPE_INSECURE);
        HttpPost req = new HttpPost(requestUrl);

        // 
        StringEntity body = null;
        try {
            body = new StringEntity(jsonBody.toJSONString(), CharEncoding.UTF_8);
        } catch (UnsupportedCharsetException e) {
            throw PersoniumCoreException.SentMessage.SM_BODY_PARSE_ERROR.reason(e);
        }
        req.setEntity(body);

        req.addHeader(PersoniumCoreUtils.HttpHeaders.X_PERSONIUM_VERSION, this.version);
        req.addHeader(HttpHeaders.AUTHORIZATION,
                OAuth2Helper.Scheme.BEARER_CREDENTIALS_PREFIX + token.toTokenString());
        req.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
        req.addHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON);

        // ?
        HttpResponse objResponse = null;
        try {
            objResponse = client.execute(req);
        } catch (Exception ioe) {
            throw PersoniumCoreException.SentMessage.SM_CONNECTION_ERROR.reason(ioe);
        }

        // ???
        String statusCode = Integer.toString(objResponse.getStatusLine().getStatusCode());
        List<OProperty<?>> properties = new ArrayList<OProperty<?>>();
        properties.add(OProperties.string(SentMessage.P_RESULT_TO.getName(), requestCellUrl));
        properties.add(OProperties.string(SentMessage.P_RESULT_CODE.getName(), statusCode));
        if (Integer.toString(HttpStatus.SC_CREATED).equals(statusCode)) {
            properties.add(OProperties.string(SentMessage.P_RESULT_REASON.getName(), "Created."));
        } else {
            properties.add(OProperties.string(SentMessage.P_RESULT_REASON.getName(), getErrorMessage(objResponse)));
        }

        return properties;

    }

    /**
     * HttpResponse??.
     * @param objResponse HttpResponse
     * @return 
     */
    private String getErrorMessage(HttpResponse objResponse) {
        JSONObject resBody = bodyAsJson(objResponse);
        String message = "";
        try {
            if (resBody != null) {
                message = (String) ((JSONObject) resBody.get("message")).get("value");
            }
        } catch (Exception e) {
            log.info(e.getMessage());
        }
        return message;
    }

    /**
     * HttpResponse?JSON??.
     * @param objResponse HttpResponse
     * @return 
     */
    private JSONObject bodyAsJson(HttpResponse objResponse) {
        JSONObject body = null;

        InputStream is = null;
        InputStreamReader isr = null;
        BufferedReader reader = null;
        String bodyString = null;
        try {
            objResponse.getHeaders("Content-Encoding");
            is = objResponse.getEntity().getContent();
            isr = new InputStreamReader(is, "UTF-8");
            reader = new BufferedReader(isr);
            StringBuffer sb = new StringBuffer();
            int chr;
            while ((chr = is.read()) != -1) {
                sb.append((char) chr);
            }
            bodyString = sb.toString();
        } catch (IllegalStateException e) {
            log.info(e.getMessage());
        } catch (IOException e) {
            log.info(e.getMessage());
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
                if (isr != null) {
                    isr.close();
                }
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                log.info(e.getMessage());
            }
        }

        try {
            if (bodyString != null) {
                body = (JSONObject) new JSONParser().parse(bodyString);
            }
        } catch (ParseException e) {
            log.info(e.getMessage());
        }

        return body;
    }

    /**
     * ??.
     * @param props OProperty
     */
    @Override
    public void validate(List<OProperty<?>> props) {
        if (ReceivedMessage.EDM_TYPE_NAME.equals(this.getEntitySetName())) {
            // ???????
            validateReceivedBoxBoundSchema(this.odataResource, propMap.get(ReceivedMessagePort.P_SCHEMA.getName()));
            validateUriCsv(ReceivedMessage.P_MULTICAST_TO.getName(),
                    propMap.get(ReceivedMessage.P_MULTICAST_TO.getName()));
            validateBody(propMap.get(ReceivedMessage.P_BODY.getName()), Common.MAX_MESSAGE_BODY_LENGTH);
            validateStatus(propMap.get(ReceivedMessage.P_TYPE.getName()),
                    propMap.get(ReceivedMessage.P_STATUS.getName()));
            validateReqRelation(propMap.get(ReceivedMessage.P_TYPE.getName()),
                    propMap.get(ReceivedMessage.P_REQUEST_RELATION.getName()),
                    propMap.get(ReceivedMessage.P_REQUEST_RELATION_TARGET.getName()));
        } else if (SentMessage.EDM_TYPE_NAME.equals(this.getEntitySetName())) {
            // ???????
            validateSentBoxBoundSchema(this.odataResource,
                    Boolean.valueOf(propMap.get(SentMessagePort.P_BOX_BOUND.getName())));
            validateUriCsv(SentMessage.P_TO.getName(), propMap.get(SentMessage.P_TO.getName()));
            validateBody(propMap.get(SentMessage.P_BODY.getName()), Common.MAX_MESSAGE_BODY_LENGTH);
            validateToAndToRelation(propMap.get(SentMessage.P_TO.getName()),
                    propMap.get(SentMessage.P_TO_RELATION.getName()));
            validateToValue(propMap.get(SentMessage.P_TO.getName()),
                    this.odataResource.getAccessContext().getBaseUri());
            validateReqRelation(propMap.get(SentMessage.P_TYPE.getName()),
                    propMap.get(SentMessage.P_REQUEST_RELATION.getName()),
                    propMap.get(SentMessage.P_REQUEST_RELATION_TARGET.getName()));
        }
    }

    /**
     * ??.
     * @param props 
     * @param
     */
    @Override
    public void collectProperties(List<OProperty<?>> props) {
        for (OProperty<?> property : props) {
            if (property.getValue() == null) {
                propMap.put(property.getName(), null);
            } else {
                propMap.put(property.getName(), property.getValue().toString());
            }
        }
    }

    /**
     * Schema check at Box Bound.
     * @param messageResource ODataResource
     * @param schema Schema
     */
    public void validateReceivedBoxBoundSchema(MessageResource messageResource, String schema) {
        if (StringUtils.isNotEmpty(schema)) {
            Box box = messageResource.getAccessContext().getCell().getBoxForSchema(schema);
            if (box == null) {
                throw PersoniumCoreException.ReceivedMessage.BOX_THAT_MATCHES_SCHEMA_NOT_EXISTS.params(schema);
            }
        }
    }

    /**
     * Schema check at Box Bound.
     * @param messageResource ODataResource
     * @param boxboundFlag BoxBoundFlag
     */
    public void validateSentBoxBoundSchema(MessageResource messageResource, boolean boxboundFlag) {
        if (boxboundFlag) {
            String schema = messageResource.getAccessContext().getSchema();
            Box box = messageResource.getAccessContext().getCell().getBoxForSchema(schema);
            if (box == null) {
                throw PersoniumCoreException.SentMessage.BOX_THAT_MATCHES_SCHEMA_NOT_EXISTS.params(schema);
            }
        }
    }

    /**
     * MulticastTo??.
     * @param propKey 
     * @param propValue 
     */
    public static void validateUriCsv(String propKey, String propValue) {
        if (propValue == null) {
            return;
        }
        if (propValue.contains(",")) {
            // CSV???????
            String[] uriList = propValue.split(",");
            for (String uri : uriList) {
                if (uri.length() != 0) {
                    if (!ODataUtils.isValidUri(uri)) {
                        throw PersoniumCoreException.OData.REQUEST_FIELD_FORMAT_ERROR.params(propKey);
                    }
                } else {
                    throw PersoniumCoreException.OData.REQUEST_FIELD_FORMAT_ERROR.params(propKey);
                }
            }
        } else {
            // CSV???????
            if (!ODataUtils.isValidUri(propValue)) {
                throw PersoniumCoreException.OData.REQUEST_FIELD_FORMAT_ERROR.params(propValue);
            }
        }
    }

    /**
     * To????baseUrl??????.
     * @param toValue to???
     * @param baseUrl baseUrl
     */
    public static void validateToValue(String toValue, String baseUrl) {
        if (toValue == null) {
            return;
        }
        // URL??
        String checkBaseUrl = null;
        String[] uriList = toValue.split(",");
        for (String uriStr : uriList) {
            try {
                URI uri = new URI(uriStr);
                checkBaseUrl = uri.getScheme() + "://" + uri.getHost();
                int port = uri.getPort();
                if (port != -1) {
                    checkBaseUrl += ":" + Integer.toString(port);
                }
                checkBaseUrl += "/";
            } catch (URISyntaxException e) {
                log.info(e.getMessage());
                throw PersoniumCoreException.OData.REQUEST_FIELD_FORMAT_ERROR.params(SentMessage.P_TO.getName());
            }

            if (checkBaseUrl == null || !checkBaseUrl.equals(baseUrl)) {
                throw PersoniumCoreException.OData.REQUEST_FIELD_FORMAT_ERROR.params(SentMessage.P_TO.getName());
            }
        }

    }

    /**
     * Body??.
     * @param value ?
     * @param maxLength 
     */
    public static void validateBody(String value, int maxLength) {
        if (value.getBytes().length > maxLength) {
            throw PersoniumCoreException.OData.REQUEST_FIELD_FORMAT_ERROR.params(ReceivedMessage.P_BODY.getName());
        }
    }

    /**
     * Status??.
     * @param type 
     * @param status 
     */
    public static void validateStatus(String type, String status) {
        // Unread if Type is message
        // None if Type is req.relation.build/req.relation.break/req.role.grant/req.role.revoke
        if (!(ReceivedMessage.TYPE_MESSAGE.equals(type) && ReceivedMessage.STATUS_UNREAD.equals(status))
                && !((ReceivedMessage.TYPE_REQ_RELATION_BUILD.equals(type)
                        || ReceivedMessage.TYPE_REQ_RELATION_BREAK.equals(type)
                        || ReceivedMessage.TYPE_REQ_ROLE_GRANT.equals(type)
                        || ReceivedMessage.TYPE_REQ_ROLE_REVOKE.equals(type))
                        && ReceivedMessage.STATUS_NONE.equals(status))) {
            throw PersoniumCoreException.OData.REQUEST_FIELD_FORMAT_ERROR
                    .params(ReceivedMessage.P_STATUS.getName());
        }
    }

    /**
     * RequestRelation??.
     * @param type 
     * @param requestRelation ?URL
     * @param requestRelationTarget ?CellURL
     */
    public static void validateReqRelation(String type, String requestRelation, String requestRelationTarget) {
        // Conditional required check
        if ((ReceivedMessage.TYPE_REQ_RELATION_BUILD.equals(type)
                || ReceivedMessage.TYPE_REQ_RELATION_BREAK.equals(type)
                || ReceivedMessage.TYPE_REQ_ROLE_GRANT.equals(type)
                || ReceivedMessage.TYPE_REQ_ROLE_REVOKE.equals(type))
                && (requestRelation == null || requestRelationTarget == null)) {
            String detail = ReceivedMessage.P_REQUEST_RELATION.getName() + ","
                    + ReceivedMessage.P_REQUEST_RELATION_TARGET.getName();
            throw PersoniumCoreException.OData.REQUEST_FIELD_FORMAT_ERROR.params(detail);
        }
        // Correlation format check
        if ((ReceivedMessage.TYPE_REQ_RELATION_BUILD.equals(type)
                || ReceivedMessage.TYPE_REQ_RELATION_BREAK.equals(type))
                && !ODataUtils.validateClassUrl(requestRelation, Common.PATTERN_RELATION_CLASS_URL)
                && !ODataUtils.validateRegEx(requestRelation, Common.PATTERN_RELATION_NAME)) {
            throw PersoniumCoreException.OData.REQUEST_FIELD_FORMAT_ERROR
                    .params(ReceivedMessage.P_REQUEST_RELATION.getName());
        } else if ((ReceivedMessage.TYPE_REQ_ROLE_GRANT.equals(type)
                || ReceivedMessage.TYPE_REQ_ROLE_REVOKE.equals(type))
                && !ODataUtils.validateClassUrl(requestRelation, Common.PATTERN_ROLE_CLASS_URL)
                && !ODataUtils.validateRegEx(requestRelation, Common.PATTERN_NAME)) {
            throw PersoniumCoreException.OData.REQUEST_FIELD_FORMAT_ERROR
                    .params(ReceivedMessage.P_REQUEST_RELATION.getName());
        }
    }

    /**
     * To-ToRelation??.
     * @param to ?URL
     * @param toRelation ????
     */
    public static void validateToAndToRelation(String to, String toRelation) {
        if (to == null && toRelation == null) {
            String detail = SentMessage.P_TO.getName() + "," + SentMessage.P_TO_RELATION.getName();
            throw PersoniumCoreException.OData.REQUEST_FIELD_FORMAT_ERROR.params(detail);
        }
    }
}