001    package com.khubla.pragmatach.framework.url;
002    
003    import java.io.ByteArrayInputStream;
004    import java.io.InputStream;
005    import java.util.ArrayList;
006    import java.util.List;
007    
008    import org.antlr.v4.runtime.ANTLRInputStream;
009    import org.antlr.v4.runtime.CommonTokenStream;
010    
011    import com.khubla.pragmatach.framework.api.PragmatachException;
012    import com.khubla.pragmatach.framework.uri.antlr4.RouteSpecificationLexer;
013    import com.khubla.pragmatach.framework.uri.antlr4.RouteSpecificationParser;
014    import com.khubla.pragmatach.framework.uri.antlr4.RouteSpecificationParser.IdsegmentContext;
015    import com.khubla.pragmatach.framework.uri.antlr4.RouteSpecificationParser.PathsegmentContext;
016    import com.khubla.pragmatach.framework.uri.antlr4.RouteSpecificationParser.RoutespecificationContext;
017    import com.khubla.pragmatach.framework.uri.antlr4.RouteSpecificationParser.SegmentContext;
018    
019    /**
020     * @author tome
021     */
022    public class RouteSpecification {
023            /**
024             * id fields
025             */
026            private final List<String> ids;
027            /**
028             * segments
029             */
030            private final List<RouteSpecificationSegment> segments;
031    
032            /**
033             * ctor
034             */
035            public RouteSpecification(String uri) throws PragmatachException {
036                    String fixedUri = uri;
037                    if (false == uri.startsWith("/")) {
038                            fixedUri = "/" + uri;
039                    }
040                    segments = parse(fixedUri);
041                    if ((null != segments) && (segments.size() > 0)) {
042                            ids = new ArrayList<String>();
043                            for (final RouteSpecificationSegment routeSpecificationSegment : segments) {
044                                    if (null != routeSpecificationSegment.getVariableId()) {
045                                            ids.add(routeSpecificationSegment.getVariableId());
046                                    }
047                            }
048                    } else {
049                            ids = null;
050                    }
051            }
052    
053            public List<String> getIds() {
054                    return ids;
055            }
056    
057            public List<RouteSpecificationSegment> getSegments() {
058                    return segments;
059            }
060    
061            /**
062             * parse an inputstream
063             */
064            private RoutespecificationContext parse(InputStream inputStream)
065                            throws PragmatachException {
066                    try {
067                            if (null != inputStream) {
068                                    final RouteSpecificationLexer routeSpecificationLexer = new RouteSpecificationLexer(
069                                                    new ANTLRInputStream(inputStream));
070                                    final CommonTokenStream tokens = new CommonTokenStream(
071                                                    routeSpecificationLexer);
072                                    final RouteSpecificationParser routeSpecificationParser = new RouteSpecificationParser(
073                                                    tokens);
074                                    return routeSpecificationParser.routespecification();
075                            } else {
076                                    throw new IllegalArgumentException();
077                            }
078                    } catch (final Exception e) {
079                            throw new PragmatachException("Exception in parse", e);
080                    }
081            }
082    
083            /**
084             * parse a URI into parts.
085             */
086            private List<RouteSpecificationSegment> parse(String uri)
087                            throws PragmatachException {
088                    try {
089                            final List<RouteSpecificationSegment> ret = new ArrayList<RouteSpecificationSegment>();
090                            /*
091                             * special case for "/"
092                             */
093                            if (uri.compareTo("/") == 0) {
094                                    RouteSpecificationSegment routeSpecificationSegment = new RouteSpecificationSegment(
095                                                    "/", null);
096                                    ret.add(routeSpecificationSegment);
097    
098                            } else {
099                                    final RoutespecificationContext routespecificationContext = parse(new ByteArrayInputStream(
100                                                    uri.getBytes("UTF-8")));
101                                    for (SegmentContext segmentContext : routespecificationContext
102                                                    .segment()) {
103                                            RouteSpecificationSegment routeSpecificationSegment = parseSegment(segmentContext);
104                                            ret.add(routeSpecificationSegment);
105                                    }
106                            }
107    
108                            return ret;
109                    } catch (final Exception e) {
110                            throw new PragmatachException("Exception in parse", e);
111                    }
112            }
113    
114            private RouteSpecificationSegment parseSegment(SegmentContext segmentContext)
115                            throws PragmatachException {
116                    try {
117                            PathsegmentContext pathsegmentContext = segmentContext.getChild(
118                                            PathsegmentContext.class, 0);
119    
120                            if (null != pathsegmentContext) {
121                                    return new RouteSpecificationSegment(
122                                                    pathsegmentContext.getText(), null);
123                            } else {
124                                    IdsegmentContext idsegmentContext = segmentContext.getChild(
125                                                    IdsegmentContext.class, 0);
126                                    if (null != idsegmentContext) {
127                                            String id = idsegmentContext.getChild(1).getText();
128                                            return new RouteSpecificationSegment(null, id);
129                                    }
130                            }
131                            return null;
132    
133                    } catch (final Exception e) {
134                            throw new PragmatachException("Exception in parseNode", e);
135                    }
136            }
137    }