org.valkyriercp.application.exceptionhandling.MessagesDialogExceptionHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.valkyriercp.application.exceptionhandling.MessagesDialogExceptionHandler.java

Source

/**
 * Copyright (C) 2015 Valkyrie RCP
 *
 * 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 org.valkyriercp.application.exceptionhandling;

import com.google.common.base.Strings;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.core.ErrorCoded;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

/**
 * Displays a message to the user which is fetched from the I18N files
 * based on the class and superclasses of the throwable.
 * <p/>
 * For example if an IllegalArgumentException is thrown, it will search for
 * java.lang.IllegalArgumentException.caption and java.lang.IllegalArgumentException.description first,
 * and if it cant find that it will try in order:
 * java.lang.RuntimeException.caption/description, java.lang.Exception.caption/description and
 * java.lang.Throwable.caption/description.
 * <p/>
 * The exception message is passed as a parameter, but is idented and wrapped first.
 * Note for the repacing of {0} to work in a property file double quotes(") need to be escaped (\")
 * and that single quotes (') should be avoided (escaping doesn't seem to work).
 * @author Geoffrey De Smet
 * @since 0.3
 */
public class MessagesDialogExceptionHandler<SELF extends MessagesDialogExceptionHandler<SELF>>
        extends AbstractDialogExceptionHandler<SELF> {

    private int wrapLength = 120;
    private int identLength = 2;

    private String messagesKey = null;

    /**
     * Sets the wrap length applied on the exception message passed as a parameter.
     * Defaults to 120.
     * @param wrapLength
     */
    public void setWrapLength(int wrapLength) {
        this.wrapLength = wrapLength;
    }

    public SELF wrappingAt(int wrapLength) {
        setWrapLength(wrapLength);
        return self();
    }

    /**
     * Sets the identation applied on the exception message passed as a parameter.
     * Defaults to 2.
     * @param identLength
     */
    public void setIdentLength(int identLength) {
        this.identLength = identLength;
    }

    public SELF withIdentLength(int identLength) {
        setIdentLength(identLength);
        return self();
    }

    /**
     * If messagesKey is set, the caption and description shown in the dialog
     * are not based dynamically on the throwable,
     * but instead statically on the keys messageKey.caption and messageKey.description.
     *
     * @param messagesKey the key used for the caption and title
     */
    public void setMessagesKey(String messagesKey) {
        this.messagesKey = messagesKey;
    }

    public SELF withMessagesKey(String messagesKey) {
        setMessagesKey(messagesKey);
        return self();
    }

    public String resolveExceptionCaption(Throwable throwable) {
        String[] messagesKeys = getMessagesKeys(throwable, ".caption");
        return getApplicationConfig().messageSourceAccessor()
                .getMessage(new DefaultMessageSourceResolvable(messagesKeys, messagesKeys[0]));
    }

    public Object createExceptionContent(Throwable throwable) {
        String[] messagesKeys = getMessagesKeys(throwable, ".description");
        String[] parameters = new String[] { formatMessage(throwable.getMessage()) };
        return getApplicationConfig().messageSourceAccessor()
                .getMessage(new DefaultMessageSourceResolvable(messagesKeys, parameters, messagesKeys[0]));
    }

    protected String[] getMessagesKeys(Throwable throwable, String keySuffix) {
        if (messagesKey != null) {
            return new String[] { messagesKey };
        }
        List<String> messageKeyList = new ArrayList<String>();
        Class clazz = throwable.getClass();
        if (throwable instanceof ErrorCoded) {
            messageKeyList.add(((ErrorCoded) throwable).getErrorCode() + keySuffix);
        }
        if (throwable instanceof SQLException) {
            messageKeyList.add(
                    SQLException.class.getName() + "." + ((SQLException) throwable).getErrorCode() + keySuffix);
        }
        while (clazz != Object.class) {
            messageKeyList.add(clazz.getName() + keySuffix);
            clazz = clazz.getSuperclass();
        }
        return messageKeyList.toArray(new String[messageKeyList.size()]);
    }

    protected String formatMessage(String message) {
        if (message == null) {
            return "";
        }
        String identString = Strings.padStart("", identLength, ' ');
        String newLineWithIdentString = "\n" + identString;
        StringBuilder formattedMessageBuilder = new StringBuilder(identString);
        StringTokenizer messageTokenizer = new StringTokenizer(message, "\n");
        while (messageTokenizer.hasMoreTokens()) {
            String messageToken = messageTokenizer.nextToken();
            formattedMessageBuilder.append(wrap(messageToken, wrapLength));
            if (messageTokenizer.hasMoreTokens()) {
                formattedMessageBuilder.append(newLineWithIdentString);
            }
        }
        return formattedMessageBuilder.toString();
    }

    private static String wrap(String str, int wrapLength) {
        int offset = 0;
        StringBuilder resultBuilder = new StringBuilder();

        while ((str.length() - offset) > wrapLength) {
            if (str.charAt(offset) == ' ') {
                offset++;
                continue;
            }

            int spaceToWrapAt = str.lastIndexOf(' ', wrapLength + offset);
            // if the next string with length maxLength doesn't contain ' '
            if (spaceToWrapAt < offset) {
                spaceToWrapAt = str.indexOf(' ', wrapLength + offset);
                // if no more ' '
                if (spaceToWrapAt < 0) {
                    break;
                }
            }

            resultBuilder.append(str.substring(offset, spaceToWrapAt));
            resultBuilder.append("\n");
            offset = spaceToWrapAt + 1;
        }

        resultBuilder.append(str.substring(offset));
        return resultBuilder.toString();
    }

}