class WebkitFlex extends AbstractCssProperty<WebkitFlex> implements StateChangeInformer<CssProperty> {

    @Override
    public WebkitFlex setCssValue(final String cssValue) {
        final String trimmedCssValue;
        if (cssValue == null) {
            throw new NullValueException(
                    "null is an invalid value. The value format should be as for example \"0 1 auto\" or initial/inherit.");
        } else if ((trimmedCssValue = TagStringUtil
                .toLowerCase(StringUtil.strip(cssValue))).isEmpty()) {
            throw new NullValueException(cssValue
                    + " is an invalid value. The value format should be as for example \"0 1 auto\" or initial/inherit.");
        }

        final String[] cssValueParts = StringUtil.splitBySpace(trimmedCssValue);

        if (cssValueParts.length > 1) {
            if (trimmedCssValue.contains(WebkitFlexBasis.INITIAL)) {
                throw new InvalidValueException(
                        "The string 'initial' makes the given cssValue invalid, please remove 'initial' from it and try.");
            }
            if (trimmedCssValue.contains(WebkitFlexBasis.INHERIT)) {
                throw new InvalidValueException(
                        "The string 'inherit' makes the given cssValue invalid, please remove 'inherit' from it and try.");
            }
        } else {
            if (PREDEFINED_CONSTANTS.contains(trimmedCssValue)) {
                if (webkitFlexGrow != null) {
                    webkitFlexGrow.setAlreadyInUse(false);
                    webkitFlexGrow = null;
                }
                if (webkitFlexShrink != null) {
                    webkitFlexShrink.setAlreadyInUse(false);
                    webkitFlexShrink = null;
                }
                if (webkitFlexBasis != null) {
                    webkitFlexBasis.setAlreadyInUse(false);
                    webkitFlexBasis = null;
                }

                this.cssValue = trimmedCssValue;
                if (getStateChangeInformer() != null) {
                    getStateChangeInformer().stateChanged(this);
                }
                return this;
            }
        }

        WebkitFlexGrow webkitFlexGrow = null;
        WebkitFlexShrink webkitFlexShrink = null;
        WebkitFlexBasis webkitFlexBasis = null;

        for (final String eachPart : cssValueParts) {
            if (webkitFlexGrow == null && WebkitFlexGrow.isValid(eachPart)) {
                if (this.webkitFlexGrow == null) {
                    webkitFlexGrow = new WebkitFlexGrow(eachPart);
                    webkitFlexGrow.setStateChangeInformer(this);
                    webkitFlexGrow.setAlreadyInUse(true);
                } else {
                    this.webkitFlexGrow.setCssValue(eachPart);
                    webkitFlexGrow = this.webkitFlexGrow;
                }
            } else if (webkitFlexShrink == null
                    && WebkitFlexShrink.isValid(eachPart)) {
                if (this.webkitFlexGrow == null) {
                    webkitFlexShrink = new WebkitFlexShrink(eachPart);
                    webkitFlexShrink.setStateChangeInformer(this);
                    webkitFlexShrink.setAlreadyInUse(true);
                } else {
                    this.webkitFlexShrink.setCssValue(eachPart);
                    webkitFlexShrink = this.webkitFlexShrink;
                }
            } else if (webkitFlexBasis == null
                    && WebkitFlexBasis.isValid(eachPart)) {
                if (this.webkitFlexBasis == null) {
                    webkitFlexBasis = new WebkitFlexBasis(eachPart);
                    webkitFlexBasis.setStateChangeInformer(this);
                    webkitFlexBasis.setAlreadyInUse(true);
                } else {
                    this.webkitFlexBasis.setCssValue(eachPart);
                    webkitFlexBasis = this.webkitFlexBasis;
                }
            }
        }

        final StringBuilder cssValueBuilder = new StringBuilder();
        boolean invalid = true;
        if (webkitFlexGrow == null) {
            if (this.webkitFlexGrow == null) {
                webkitFlexGrow = new WebkitFlexGrow(1);
                webkitFlexGrow.setStateChangeInformer(this);
                webkitFlexGrow.setAlreadyInUse(true);
            } else {
                this.webkitFlexGrow.setValue(0);
                webkitFlexGrow = this.webkitFlexGrow;
            }
        } else {
            invalid = false;
        }

        cssValueBuilder.append(webkitFlexGrow.getCssValue()).append(' ');

        if (webkitFlexShrink == null) {
            if (this.webkitFlexShrink == null) {
                webkitFlexShrink = new WebkitFlexShrink(1);
                webkitFlexShrink.setStateChangeInformer(this);
                webkitFlexShrink.setAlreadyInUse(true);
            } else {
                this.webkitFlexShrink.setValue(1);
                webkitFlexShrink = this.webkitFlexShrink;
            }
        } else {
            invalid = false;
        }

        cssValueBuilder.append(webkitFlexShrink.getCssValue()).append(' ');

        if (webkitFlexBasis == null) {
            if (cssValueParts.length == 3) {
                throw new InvalidValueException(
                        "the given cssValue contains invalid flex-basis value.");
            }
            if (this.webkitFlexBasis == null) {
                webkitFlexBasis = new WebkitFlexBasis(0);
                webkitFlexBasis.setStateChangeInformer(this);
                webkitFlexBasis.setAlreadyInUse(true);
            } else {
                this.webkitFlexBasis.setAsAuto();
                webkitFlexBasis = this.webkitFlexBasis;
            }
        } else {
            invalid = false;
        }

        cssValueBuilder.append(webkitFlexBasis.getCssValue());

        if (invalid) {
            throw new InvalidValueException(cssValue
                    + " is an invalid value. The value format should be as for example \"0 1 auto\" or initial/inherit.");
        }
        this.cssValue = cssValueBuilder.toString();

        webkitFlexGrow.setStateChangeInformer(this);
        webkitFlexGrow.setAlreadyInUse(true);

        webkitFlexShrink.setStateChangeInformer(this);
        webkitFlexShrink.setAlreadyInUse(true);

        webkitFlexBasis.setStateChangeInformer(this);
        webkitFlexBasis.setAlreadyInUse(true);

        this.webkitFlexGrow = webkitFlexGrow;
        this.webkitFlexShrink = webkitFlexShrink;
        this.webkitFlexBasis = webkitFlexBasis;

        if (getStateChangeInformer() != null) {
            getStateChangeInformer().stateChanged(this);
        }

        return this;
    }

    public  WebkitFlex();
    public  WebkitFlex(final String cssValue);
    public  WebkitFlex(final WebkitFlex webkitFlex);

}