class BorderImageSlice extends AbstractCssProperty<BorderImageSlice> {

    @Override
    public BorderImageSlice setCssValue(final String cssValue) {
        if (cssValue == null) {
            throw new NullValueException(
                    "null is an invalid value. The value format should be as for example 75px or 85%. Or, initial/inherit/medium/thin/thick.");
        } else if (StringUtil.isBlank(cssValue)) {
            throw new InvalidValueException(
                    "blank string is an invalid value. The value format should be as for example 75px or 85%. Or, initial/inherit/medium/thin/thick.");
        } else {

            final String previousCssValue = this.cssValue;
            final String previousMiddle = middle;

            final CssLengthUnit previousTopUnit = topUnit;
            final CssLengthUnit previousRightUnit = rightUnit;
            final CssLengthUnit previousBottomUnit = bottomUnit;
            final CssLengthUnit previousLeftUnit = leftUnit;

            final Float previousTop = top;
            final Float previousRight = right;
            final Float previousBottom = bottom;
            final Float previousLeft = left;
            try {
                final String trimmedCssValue = TagStringUtil
                        .toLowerCase(StringUtil.strip(cssValue));

                if (PREDEFINED_CONSTANTS.contains(trimmedCssValue)) {
                    this.cssValue = trimmedCssValue;
                    top = right = bottom = left = null;
                    topUnit = rightUnit = bottomUnit = leftUnit = null;
                    if (getStateChangeInformer() != null) {
                        getStateChangeInformer().stateChanged(this);
                    }
                    return this;
                }

                final String cssValueWithoutFill = trimmedCssValue.replace(FILL,
                        "");

                final int lengthOfFill = FILL.length();

                final int lengthWithFill = cssValueWithoutFill.length()
                        + lengthOfFill;

                final int lengthBeforeRemovingFill = trimmedCssValue.length();

                if ((lengthBeforeRemovingFill - lengthWithFill) > 0) {
                    throw new InvalidValueException("The given cssValue '"
                            + cssValue
                            + "' is invalid as it contains more that one 'fill' value.");
                }

                middle = lengthBeforeRemovingFill == lengthWithFill ? FILL
                        : null;

                final String convertedToSingleSpace = StringUtil
                        .convertToSingleSpace(
                                StringUtil.strip(cssValueWithoutFill));

                if (!StringUtil.isBlank(convertedToSingleSpace)) {

                    final String[] extractedSlices = StringUtil
                            .splitBySpace(convertedToSingleSpace);

                    if (extractedSlices.length == 1) {
                        final Object[] lengthValueAndUnitAll = CssLengthUtil
                                .getLengthValueAndUnit(extractedSlices[0]);
                        if (lengthValueAndUnitAll.length == 2) {
                            top = right = bottom = left = (Float) lengthValueAndUnitAll[0];
                            topUnit = rightUnit = bottomUnit = leftUnit = (CssLengthUnit) lengthValueAndUnitAll[1];
                        } else if (lengthValueAndUnitAll.length == 1) {
                            top = right = bottom = left = (Float) lengthValueAndUnitAll[0];
                            topUnit = rightUnit = bottomUnit = leftUnit = null;
                        } else {
                            throw new InvalidValueException("'"
                                    + extractedSlices[0] + "' is invalid in '"
                                    + cssValue + "'");
                        }

                    } else if (extractedSlices.length == 2) {

                        final Object[] lengthValueAndUnitTopBottom = CssLengthUtil
                                .getLengthValueAndUnit(extractedSlices[0]);

                        if (lengthValueAndUnitTopBottom.length == 2) {
                            top = bottom = (Float) lengthValueAndUnitTopBottom[0];
                            topUnit = bottomUnit = (CssLengthUnit) lengthValueAndUnitTopBottom[1];
                        } else if (lengthValueAndUnitTopBottom.length == 1) {
                            top = bottom = (Float) lengthValueAndUnitTopBottom[0];
                            topUnit = bottomUnit = null;
                        } else {
                            throw new InvalidValueException("'"
                                    + extractedSlices[0] + "' is invalid in '"
                                    + cssValue + "'");
                        }

                        final Object[] lengthValueAndUnitRightLeft = CssLengthUtil
                                .getLengthValueAndUnit(extractedSlices[1]);

                        if (lengthValueAndUnitRightLeft.length == 2) {
                            right = left = (Float) lengthValueAndUnitRightLeft[0];
                            rightUnit = leftUnit = (CssLengthUnit) lengthValueAndUnitRightLeft[1];
                        } else if (lengthValueAndUnitRightLeft.length == 1) {
                            right = left = (Float) lengthValueAndUnitRightLeft[0];
                            rightUnit = leftUnit = null;
                        } else {
                            throw new InvalidValueException("'"
                                    + extractedSlices[1] + "' is invalid in '"
                                    + cssValue + "'");
                        }

                    } else if (extractedSlices.length == 3) {

                        final Object[] lengthValueAndUnitTop = CssLengthUtil
                                .getLengthValueAndUnit(extractedSlices[0]);
                        if (lengthValueAndUnitTop.length == 2) {
                            top = (Float) lengthValueAndUnitTop[0];
                            topUnit = (CssLengthUnit) lengthValueAndUnitTop[1];
                        } else if (lengthValueAndUnitTop.length == 1) {
                            top = (Float) lengthValueAndUnitTop[0];
                            topUnit = null;
                        } else {
                            throw new InvalidValueException("'"
                                    + extractedSlices[0] + "' is invalid in '"
                                    + cssValue + "'");
                        }

                        final Object[] lengthValueAndUnitRightLeft = CssLengthUtil
                                .getLengthValueAndUnit(extractedSlices[1]);
                        if (lengthValueAndUnitRightLeft.length == 2) {
                            right = left = (Float) lengthValueAndUnitRightLeft[0];
                            rightUnit = leftUnit = (CssLengthUnit) lengthValueAndUnitRightLeft[1];
                        } else if (lengthValueAndUnitRightLeft.length == 1) {
                            right = left = (Float) lengthValueAndUnitRightLeft[0];
                            rightUnit = leftUnit = null;
                        } else {
                            throw new InvalidValueException("'"
                                    + extractedSlices[1] + "' is invalid in '"
                                    + cssValue + "'");
                        }

                        final Object[] lengthValueAndUnitBottom = CssLengthUtil
                                .getLengthValueAndUnit(extractedSlices[2]);
                        if (lengthValueAndUnitBottom.length == 2) {
                            bottom = (Float) lengthValueAndUnitBottom[0];
                            bottomUnit = (CssLengthUnit) lengthValueAndUnitBottom[1];
                        } else if (lengthValueAndUnitBottom.length == 1) {
                            bottom = (Float) lengthValueAndUnitBottom[0];
                            bottomUnit = null;
                        } else {
                            throw new InvalidValueException("'"
                                    + extractedSlices[2] + "' is invalid in '"
                                    + cssValue + "'");
                        }

                    } else if (extractedSlices.length == 4) {

                        final Object[] lengthValueAndUnitTop = CssLengthUtil
                                .getLengthValueAndUnit(extractedSlices[0]);
                        if (lengthValueAndUnitTop.length == 2) {
                            top = (Float) lengthValueAndUnitTop[0];
                            topUnit = (CssLengthUnit) lengthValueAndUnitTop[1];
                        } else if (lengthValueAndUnitTop.length == 1) {
                            top = (Float) lengthValueAndUnitTop[0];
                            topUnit = null;
                        } else {
                            throw new InvalidValueException("'"
                                    + extractedSlices[0] + "' is invalid in '"
                                    + cssValue + "'");
                        }

                        final Object[] lengthValueAndUnitRight = CssLengthUtil
                                .getLengthValueAndUnit(extractedSlices[1]);
                        if (lengthValueAndUnitRight.length == 2) {
                            right = (Float) lengthValueAndUnitRight[0];
                            rightUnit = (CssLengthUnit) lengthValueAndUnitRight[1];
                        } else if (lengthValueAndUnitRight.length == 1) {
                            right = (Float) lengthValueAndUnitRight[0];
                            rightUnit = null;
                        } else {
                            throw new InvalidValueException("'"
                                    + extractedSlices[1] + "' is invalid in '"
                                    + cssValue + "'");
                        }
                        final Object[] lengthValueAndUnitBottom = CssLengthUtil
                                .getLengthValueAndUnit(extractedSlices[2]);
                        if (lengthValueAndUnitBottom.length == 2) {
                            bottom = (Float) lengthValueAndUnitBottom[0];
                            bottomUnit = (CssLengthUnit) lengthValueAndUnitBottom[1];
                        } else if (lengthValueAndUnitBottom.length == 1) {
                            bottom = (Float) lengthValueAndUnitBottom[0];
                            bottomUnit = null;
                        } else {
                            throw new InvalidValueException("'"
                                    + extractedSlices[2] + "' is invalid in '"
                                    + cssValue + "'");
                        }

                        final Object[] lengthValueAndUnitLeft = CssLengthUtil
                                .getLengthValueAndUnit(extractedSlices[3]);
                        if (lengthValueAndUnitLeft.length == 2) {
                            left = (Float) lengthValueAndUnitLeft[0];
                            leftUnit = (CssLengthUnit) lengthValueAndUnitLeft[1];
                        } else if (lengthValueAndUnitLeft.length == 1) {
                            left = (Float) lengthValueAndUnitLeft[0];
                            leftUnit = null;
                        } else {
                            throw new InvalidValueException("'"
                                    + extractedSlices[3] + "' is invalid in '"
                                    + cssValue + "'");
                        }

                    } else {
                        throw new InvalidValueException(
                                "the given cssValue is invalid");
                    }
                }
                this.cssValue = getProducedCssValue(top, topUnit, right,
                        rightUnit, bottom, bottomUnit, left, leftUnit, middle);
                if (getStateChangeInformer() != null) {
                    getStateChangeInformer().stateChanged(this);
                }
            } catch (final InvalidValueException e) {
                this.cssValue = previousCssValue;
                middle = previousMiddle;

                topUnit = previousTopUnit;
                rightUnit = previousRightUnit;
                bottomUnit = previousBottomUnit;
                leftUnit = previousLeftUnit;

                top = previousTop;
                right = previousRight;
                bottom = previousBottom;
                left = previousLeft;
                throw e;
            }
        }
        return this;
    }

    public  BorderImageSlice();
    public  BorderImageSlice(final String cssValue);
    public  BorderImageSlice(final BorderImageSlice bottom);
    public  BorderImageSlice(final float percent);
    public  BorderImageSlice(final float value,
            final CssLengthUnit cssLengthUnit);

}