001package org.unix4j.convert;
002
003import org.unix4j.util.Range;
004
005import java.util.ArrayList;
006import java.util.List;
007
008public class RangeConverters {
009        public static final ValueConverter<Range> STRING = new ValueConverter<Range>() {
010                @Override
011                public Range convert(Object value) throws IllegalArgumentException {
012                        if (value != null) {
013                                final String[] values = value.toString().split("\\s*,\\s*");
014                                final List<Integer> indices = new ArrayList<Integer>();
015                                for (final String s : values) {
016                                        final int dashIndex = s.indexOf('-');
017                                        try {
018                                                if (dashIndex < 0) {
019                                                        indices.add(Integer.parseInt(s));
020                                                } else {
021                                                        if (dashIndex == 0) {
022                                                                //e.g.: -4
023                                                                indices.add(Integer.parseInt(s));
024                                                        } else if (dashIndex == s.length() - 1) {
025                                                                //e.g.: 4-
026                                                                indices.add(Integer.parseInt(s.substring(0, dashIndex)));
027                                                                indices.add(-Integer.MAX_VALUE);//FIXME not very nice, but works
028                                                        } else {
029                                                                //e.g. 4-8
030                                                                indices.add(Integer.parseInt(s.substring(0, dashIndex)));
031                                                                indices.add(Integer.parseInt(s.substring(dashIndex)));//include minus
032                                                        }
033                                                }
034                                        } catch (Exception e) {
035                                                //we cannot parse range value, return null
036                                                return null;
037                                        }
038                                }
039                                if (!indices.isEmpty()) {
040                                        return toRange(value, indices);
041                                }
042                        }
043                        return null;
044                }
045                private Range toRange(final Object value, final List<Integer> indices) {
046                        int lastIndex = 0;
047                        Range range = null;
048                        for (final int index : indices) {
049                                if (index == 0) {
050                                        throw new IllegalArgumentException("invalid index 0 in range expression: " + value);
051                                }
052                                if (index > 0) {
053                                        if (lastIndex > 0) {
054                                                range = range == null ? Range.of(lastIndex) : range.andOf(lastIndex);
055                                        }
056                                        lastIndex = index;
057                                } else {
058                                        final int start = lastIndex == 0 ? 1 : lastIndex;
059                                        range = range == null ? Range.between(start, -index) : range.andBetween(start, -index);
060                                        lastIndex = -1;
061                                }
062                        }
063                        if (lastIndex > 0) {
064                                return range == null ? Range.of(lastIndex) : range.andOf(lastIndex);
065                        }
066                        return range;
067                }
068
069        };
070        public static final ValueConverter<Range> DEFAULT = STRING;
071}