com.sap.core.odata.core.edm.EdmBinary.java Source code

Java tutorial

Introduction

Here is the source code for com.sap.core.odata.core.edm.EdmBinary.java

Source

/*******************************************************************************
 * Copyright 2013 SAP AG
 * 
 * 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 com.sap.core.odata.core.edm;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;

import com.sap.core.odata.api.edm.EdmFacets;
import com.sap.core.odata.api.edm.EdmLiteralKind;
import com.sap.core.odata.api.edm.EdmSimpleTypeException;

/**
 * Implementation of the EDM simple type Binary.
 * @author SAP AG
 */
public class EdmBinary extends AbstractSimpleType {

    private static final EdmBinary instance = new EdmBinary();

    public static EdmBinary getInstance() {
        return instance;
    }

    @Override
    public Class<?> getDefaultType() {
        return byte[].class;
    }

    @Override
    public boolean validate(final String value, final EdmLiteralKind literalKind, final EdmFacets facets) {
        if (value == null) {
            return facets == null || facets.isNullable() == null || facets.isNullable();
        }

        if (literalKind == null) {
            return false;
        }

        return validateLiteral(value, literalKind) && validateMaxLength(value, literalKind, facets);
    }

    private static boolean validateLiteral(final String value, final EdmLiteralKind literalKind) {
        return literalKind == EdmLiteralKind.URI ? value.matches("(?:X|binary)'(?:\\p{XDigit}{2})*'")
                : Base64.isBase64(value);
    }

    private static boolean validateMaxLength(final String value, final EdmLiteralKind literalKind,
            final EdmFacets facets) {
        return facets == null || facets.getMaxLength() == null ? true : literalKind == EdmLiteralKind.URI ?
        // In URI representation, each byte is represented as two hexadecimal digits;
        // additionally, we have to account for the prefix and the surrounding "'"s.
                facets.getMaxLength() >= (value.length() - (value.startsWith("X") ? 3 : 8)) / 2 :
                // In default representation, every three bytes are represented as four base-64 characters.
                // Additionally, there could be up to two padding "=" characters if the number of bytes is
                // not a multiple of three, and there could be carriage return/line feed combinations.
                facets.getMaxLength() >= value.length() * 3 / 4
                        - (value.endsWith("==") ? 2 : value.endsWith("=") ? 1 : 0) - crlfLength(value);
    }

    private static int crlfLength(final String value) {
        int result = 0;
        int index = 0;
        while (index >= 0) {
            index = value.indexOf("\r\n", index);
            if (index > 0) {
                result++;
                index++;
            }
        }
        return result * 2;
    }

    @Override
    protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind,
            final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
        if (!validateLiteral(value, literalKind)) {
            throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
        }
        if (!validateMaxLength(value, literalKind, facets)) {
            throw new EdmSimpleTypeException(
                    EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED.addContent(value, facets));
        }

        byte[] result;
        if (literalKind == EdmLiteralKind.URI) {
            try {
                result = Hex.decodeHex(
                        value.substring(value.startsWith("X") ? 2 : 7, value.length() - 1).toCharArray());
            } catch (final DecoderException e) {
                throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value),
                        e);
            }
        } else {
            result = Base64.decodeBase64(value);
        }

        if (returnType.isAssignableFrom(byte[].class)) {
            return returnType.cast(result);
        } else if (returnType.isAssignableFrom(Byte[].class)) {
            Byte[] byteArray = new Byte[result.length];
            for (int i = 0; i < result.length; i++) {
                byteArray[i] = result[i];
            }
            return returnType.cast(byteArray);
        } else {
            throw new EdmSimpleTypeException(
                    EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
        }
    }

    @Override
    protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind,
            final EdmFacets facets) throws EdmSimpleTypeException {
        byte[] byteArrayValue;
        if (value instanceof byte[]) {
            byteArrayValue = (byte[]) value;
        } else if (value instanceof Byte[]) {
            final int length = ((Byte[]) value).length;
            byteArrayValue = new byte[length];
            for (int i = 0; i < length; i++) {
                byteArrayValue[i] = ((Byte[]) value)[i].byteValue();
            }
        } else {
            throw new EdmSimpleTypeException(
                    EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(value.getClass()));
        }

        if (facets != null && facets.getMaxLength() != null && byteArrayValue.length > facets.getMaxLength()) {
            throw new EdmSimpleTypeException(
                    EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED.addContent(value, facets));
        }

        return Base64.encodeBase64String(byteArrayValue);
    }

    @Override
    public String toUriLiteral(final String literal) throws EdmSimpleTypeException {
        return "binary'" + String.valueOf(Hex.encodeHex(Base64.decodeBase64(literal), false)) + "'";
    }
}