001 package com.thaiopensource.validate.nrl; 002 003 import com.thaiopensource.xml.util.Naming; 004 005 import java.util.Vector; 006 007 class Path { 008 private final boolean root; 009 private final Vector names; 010 011 Path(boolean root, Vector names) { 012 this.root = root; 013 this.names = names; 014 } 015 016 boolean isRoot() { 017 return root; 018 } 019 020 Vector getNames() { 021 return names; 022 } 023 024 public String toString() { 025 StringBuffer buf = new StringBuffer(); 026 if (root) 027 buf.append('/'); 028 for (int i = 0, len = names.size(); i < len; i++) { 029 if (i != 0) 030 buf.append('/'); 031 buf.append((String)names.elementAt(i)); 032 } 033 return buf.toString(); 034 } 035 036 static class ParseException extends Exception { 037 private final String messageKey; 038 039 ParseException(String messageKey) { 040 super(messageKey); 041 this.messageKey = messageKey; 042 } 043 044 public String getMessageKey() { 045 return messageKey; 046 } 047 } 048 049 private static final int START = 0; 050 private static final int IN_NAME = 1; 051 private static final int AFTER_NAME = 2; 052 private static final int AFTER_SLASH = 3; 053 054 static Vector parse(String str) throws ParseException { 055 int state = START; 056 int nameStartIndex = -1; 057 Vector paths = new Vector(); 058 Vector names = new Vector(); 059 boolean root = false; 060 for (int i = 0, len = str.length(); i < len; i++) { 061 char c = str.charAt(i); 062 switch (c) { 063 case ' ': 064 case '\r': 065 case '\n': 066 case '\t': 067 if (state == IN_NAME) { 068 names.addElement(makeName(str, nameStartIndex, i)); 069 state = AFTER_NAME; 070 } 071 break; 072 case '/': 073 switch (state) { 074 case IN_NAME: 075 names.addElement(makeName(str, nameStartIndex, i)); 076 break; 077 case START: 078 root = true; 079 break; 080 case AFTER_SLASH: 081 throw new ParseException("unexpected_slash"); 082 } 083 state = AFTER_SLASH; 084 break; 085 case '|': 086 switch (state) { 087 case START: 088 throw new ParseException("empty_path"); 089 case AFTER_NAME: 090 break; 091 case AFTER_SLASH: 092 throw new ParseException("expected_name"); 093 case IN_NAME: 094 names.addElement(makeName(str, nameStartIndex, i)); 095 break; 096 } 097 paths.addElement(new Path(root, names)); 098 root = false; 099 names = new Vector(); 100 state = START; 101 break; 102 default: 103 switch (state) { 104 case AFTER_NAME: 105 throw new ParseException("expected_slash"); 106 case AFTER_SLASH: 107 case START: 108 nameStartIndex = i; 109 state = IN_NAME; 110 break; 111 case IN_NAME: 112 break; 113 } 114 break; 115 } 116 } 117 switch (state) { 118 case START: 119 throw new ParseException("empty_path"); 120 case AFTER_NAME: 121 break; 122 case AFTER_SLASH: 123 throw new ParseException("expected_name"); 124 case IN_NAME: 125 names.addElement(makeName(str, nameStartIndex, str.length())); 126 break; 127 } 128 paths.addElement(new Path(root, names)); 129 return paths; 130 } 131 132 private static String makeName(String str, int start, int end) throws ParseException { 133 String name = str.substring(start, end); 134 if (!Naming.isNcname(name)) 135 throw new ParseException("invalid_name"); 136 return name; 137 } 138 139 static public void main(String[] args) throws ParseException { 140 Vector paths = parse(args[0]); 141 for (int i = 0; i < paths.size(); i++) { 142 if (i != 0) 143 System.out.println("---"); 144 Path path = (Path)paths.elementAt(i); 145 if (path.isRoot()) 146 System.out.println("/"); 147 for (int j = 0; j < path.getNames().size(); j++) 148 System.out.println(path.getNames().elementAt(j)); 149 } 150 } 151 }