001: /*
002: * Created on 14.02.2005
003: *
004: */
005: package org.ontoware.rdfreactor.generator;
006:
007: import java.util.HashMap;
008: import java.util.List;
009: import java.util.Map;
010: import java.util.Set;
011:
012: import org.apache.commons.logging.Log;
013: import org.apache.commons.logging.LogFactory;
014: import org.ontoware.rdf2go.model.node.BlankNode;
015: import org.ontoware.rdf2go.model.node.URI;
016: import org.ontoware.rdfreactor.schema.bootstrap.Resource;
017:
018: /**
019: * Helper methods for creating legal and unique Java Bean Identifiers for
020: * resources.
021: *
022: * Use toBeanName() as the main entry point to the helper functions.
023: *
024: * @author mvo
025: */
026: public class JavaNamingUtils {
027:
028: private static Log log = LogFactory.getLog(JavaNamingUtils.class);
029:
030: /**
031: * Create a legal and unique Java Bean Identifier for a resource.
032: *
033: * @param rresource -
034: * Resource for which to create the Identifier
035: * @param usedNames -
036: * Set of already used names
037: * @return a new unique name from label or URI
038: */
039: public static String toBeanName(Resource rresource,
040: Set<String> usedNames) {
041: // if we have at least one label, we use that
042: List<String> labels = rresource.getAllLabel_asList();
043: // TODO improve: language handling in labels
044: if (labels.size() > 0) {
045: log.debug("Found a label, using first label: "
046: + labels.get(0));
047: String labelName = toLegalJavaIdentifier(labels.get(0));
048: if (!usedNames.contains(labelName))
049: return labelName;
050: // IMPROVE: might try other labels
051: else {
052: String result = uri2beanname(rresource.getResource(),
053: usedNames);
054: log.debug("NAME "
055: + rresource.getResource().toSPARQL()
056: + " label '" + labelName
057: + "' is already used. Using '" + result
058: + "' computed from URI.");
059: return result;
060: }
061: } else {
062: String result = uri2beanname(rresource.getResource(),
063: usedNames);
064: log.debug("NAME " + rresource.getResource().toSPARQL()
065: + " found no label. Using '" + result
066: + "' computed from URI.");
067: return result;
068: }
069: }
070:
071: /**
072: * Convert any String into a legal Java Bean Identifier (no spaces,
073: * everything concatenated)
074: *
075: * @param illegal -
076: * String which has to be converted
077: * @return legal Java Bean Identifier
078: */
079: public static String toLegalJavaIdentifier(String illegal) {
080: assert illegal != null;
081:
082: // make rawname bean-style
083: // remove all spaces/underlines and concatenate the result
084: String beanname = illegal;
085: // FIXME dirty hack
086: beanname = beanname.replaceAll("is ", "");
087: beanname = beanname.replaceAll("has ", "");
088: beanname = beanname.replaceAll("is_", "");
089: beanname = beanname.replaceAll("has_", "");
090: beanname = beanname.replaceAll(" ", "");
091: beanname = beanname.replaceAll("_", "");
092:
093: beanname = beanname.replaceAll("[^a-zA-Z0-9]", "_");
094: beanname = beanname.trim();
095:
096: // force a letter as first character (e.g. no number)
097: if (!"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
098: .contains(beanname.substring(0, 1)))
099: beanname = "a_" + beanname;
100:
101: // first letter upperacse
102: beanname = beanname.substring(0, 1).toUpperCase()
103: + beanname.substring(1);
104:
105: assert beanname != null;
106: return beanname;
107: }
108:
109: /**
110: * Take a URI and generate a legal and unique Java Bean Identifier from it.
111: *
112: * @param uriOrBlankNode -
113: * URI or BlankNode for which a bean identifiers has to be
114: * created.
115: * @param usedNames -
116: * Set of alread used bean identifiers
117: * @return a legal and unique Java Bean Identifier
118: */
119: public static String uri2beanname(Object uriOrBlankNode,
120: Set<String> usedNames) {
121:
122: if (uriOrBlankNode instanceof BlankNode) {
123: return "blankNode";
124: // TODO create names for anonymous resource
125: // throw new RuntimeException(
126: // "Cannot create names for anonymous resources (yet)");
127: }
128:
129: URI uri = (URI) uriOrBlankNode;
130:
131: String rawname;
132: if (uri != null) {
133: if (getLocalPart(uri.toString()) != null)
134: rawname = getLocalPart(uri.toString());
135: else
136: rawname = uri.toString();
137: } else {
138: // generate name! only needed for blank nodes
139: rawname = "genBean" + System.currentTimeMillis();
140: }
141:
142: // remove preceeding 'has'
143: if (rawname.toLowerCase().startsWith("has")
144: && rawname.length() > 3)
145: rawname = rawname.substring(3);
146:
147: // make rawname bean-style
148: String beanname = toLegalJavaIdentifier(rawname);
149:
150: // now we have a nice bean name - but is it unique?
151: if (usedNames.contains(beanname)) {
152:
153: // try to use namespace prefix for disambiguation
154: String namespacePrefix = guessNSPrefix(uri.toString());
155: String prefixedBeanName = toLegalJavaIdentifier(namespacePrefix
156: + beanname);
157: if (usedNames.contains(prefixedBeanName))
158: // fallback to plain uri
159: beanname = toLegalJavaIdentifier(uri.toString());
160: else
161: beanname = prefixedBeanName;
162: }
163:
164: return beanname;
165: }
166:
167: /**
168: * Get the local part of a URI, which is the fragment identifier (after #)
169: * or part after the last / .
170: *
171: * @param uriString -
172: * URI given as String
173: * @return URI fragment identifier OR part after last slash OR null
174: */
175: public static String getLocalPart(String uriString) {
176:
177: String fragment = null;
178: if (uriString.contains("#")) {
179: fragment = uriString
180: .substring(uriString.lastIndexOf('#') + 1);
181: if (fragment != null && fragment.length() > 0) {
182: return fragment;
183: }
184: }
185:
186: // IV: no fragment, but some URI
187: int slashPos = uriString.lastIndexOf('/');
188: if (slashPos > 0 && slashPos + 1 < uriString.length()) {
189: // take after last slash
190: return uriString.substring(slashPos + 1);
191: } else {
192: int colonPos = uriString.lastIndexOf(':');
193: if (colonPos > 0 && colonPos + 1 < uriString.length()) {
194: // take after last slash
195: return uriString.substring(colonPos + 1);
196: } else {
197: return null;
198: }
199: }
200: }
201:
202: /**
203: * Get the Name Space Part of an URI (before the # or last / )
204: *
205: * @param uriString -
206: * URI given as String
207: * @return the part BEFORE the # or last slash
208: */
209: public static String getNamespacePart(String uriString) {
210: String local = getLocalPart(uriString);
211: if (local == null)
212: return null;
213:
214: return uriString.substring(0, uriString.length()
215: - local.length());
216: }
217:
218: /**
219: * try to find a suitable prefix to represent a uri, much like the prefixed
220: * used in N3 notation.
221: *
222: * @param uriString
223: * a URI given as String
224: * @return a short, lowercase name without spaces, usable as a N3 namespace
225: * prefix
226: */
227: public static String guessNSPrefix(String uriString) {
228:
229: // TODO improve: later loaded from file
230: Map<String, String> namespace2prefix = new HashMap<String, String>();
231: namespace2prefix.put("http://xmlns.com/foaf/0.1/", "foaf");
232: namespace2prefix.put("http://www.w3.org/2002/07/owl#", "owl");
233: namespace2prefix.put(
234: "http://www.w3.org/1999/02/22-rdf-syntax-ns#", "rdf");
235: namespace2prefix.put("http://www.w3.org/2000/01/rdf-schema#",
236: "rdfs");
237: namespace2prefix.put("http://www.w3.org/2002/12/cal/ical#",
238: "ical");
239: namespace2prefix
240: .put("http://xmlns.com/wordnet/1.6/", "wordnet");
241: namespace2prefix.put("http://musicbrainz.org/mm/mm-2.1#",
242: "musicbrainz21");
243:
244: // look up known namespaces
245: String nspart = getNamespacePart(uriString);
246: if (namespace2prefix.containsKey(nspart.toLowerCase())) {
247: return namespace2prefix.get(nspart.toLowerCase());
248: } else {
249:
250: String[] slashparts = nspart.substring(0,
251: nspart.length() - 1).split("/");
252: int i = slashparts.length - 1;
253: boolean foundAlphabetic = false;
254: String name = "";
255: while (i > 0 && !foundAlphabetic) {
256:
257: if (slashparts[i].matches("[a-zA-Z]+")) {
258: foundAlphabetic = true;
259: }
260:
261: name = slashparts[i] + "_" + name;
262: i--;
263: }
264: log.debug("made name |" + name + "|");
265: return name;
266: }
267: }
268:
269: }
|