Nombres Mixtos
Recordamos que un nombre
mixto es un nombre que expande varios sistemas de nombres. Aquí tenemos un
ejemplo de un nombre mixto.
cn=homedir,cn=Jon Ruiz,ou=People/tutorial/report.txt
Esta es la representación string de un nombre mixto que contiene dos partes: un
nombre LDAP, "cn=homedir,cn=Jon Ruiz,ou=People", y un
nombre de fichero, "tutorial/report.txt". cuando pasamos
este string a un método de Context,
como lookup(),
en el espacio de nombres configurado segun las recomendaciones de este tutorial
(ver la lección Preparaciones),
el método resolverá a través del directorio LDAP al sistema de ficheros y
devolverá el objeto destino (un fichero). El mecanismo de cómo se consigue
esto mediante las implementaciones subyacentes del proveedor de servicio se
describe en la lección Federación.
Aquí tenemos un
ejemplo.
File f = (File)ctx.lookup(
"cn=homedir,cn=Jon Ruiz,ou=People/tutorial/report.txt");
Representación String
Un nombre mixto está compuesto por componentes. Podemos pensar en un
componente como en un segmento del nombre mixto que pertenece a un sólo sistema
de nombres. Cada compontente está separado por un barra inclinada ("/").
Por ejemplo, el nombre.
cn=homedir,cn=Jon Ruiz,ou=People/tutorial/report.txt
tiene tres componentes.
cn=homedir,cn=Jon Ruiz,ou=People
tutorial
report.txt
El primer componente pertenece al espacio de nombres LDAP, y el segundo
pertenece al espacio de nombres de sistema de ficheros. Como podemos ver de este
ejemplo, se permiten varios componentes del mismo espacio de nombres ("tutorial"
y "report.txt" son del espacio de nombres del sistema
de ficheros), pero un componente no puede expandirse a más de un espacio de
nombres (ver la explicación en la lección Federación.)
Además de los caracteres de la barra inclinada, la síntaxis de nombres
mixtos también permite otros caracteres especiales: la barra inclinada
invertida ("\"), la comilla simple ("'"),
y las comillas ("""). Estos caracteres se llaman
metacaracteres, lo que significa que tienen un significado especial cuando
aparecen en un nombre mixto. El caracter de barra invertida es el caracter de
escape. cuando el caracter de escape precede a un caracter meta, el caracter
meta se trata literalmente y no se interpreta de acuerdo a su significado
especial. Por ejemplo, en el string a\/b, la barra inclinada es
escapada por el caracter de escape (barra invertida) y por lo tanto no es
tratada como un separador de nombre de componente. Puedes ver la sección Manejar
Caracteres Especiales de esta lección para más detalles sobre los
caracteres especiales.
Las comillas se proporcionan para que podamos usar los metacaracteres dentro
de un componente de nombre mixto sin tener que escaparlos. Cuando un componente
está entre comillado, el primer y último caracter deben ser (el mismo) caracte
de comilla. Un caracter de comilla simple debe corresponder con otro caracter de
comilla simple, etc. Aquí tenemos tres ejemplos del mismo componente escrito usando
caracteres de escape y comillas.
a\/b\/c\/d
"a/b/c/d"
'a/b/b/d'
Se permtien dos caracteres de comillas diferentes para poder entrecomillar
cuando ya existe una comilla en el componente. Por ejemplo un componente que
contiene un entrecomillado doble podría ser representado por \"ab
o por '"ab'.
Un nombre mixto puede estar vacío; es decir, contener cero
componentes. Un nombre mixto vacío se representa por un string vacío.
Un nombre de componente mixto puedo estar vacío; es decir, contiene
un string vacío. Un separador de componente inicial (el nombre mixto empieza
con un separador) denota un inicio de componente vacío. Un separador de
componente final (el nombre mixto termina con un separador) denota una parte
final de componente vacía. Separadores de componentes adyacentes denotan un
componente vacío. Aquí tenemos algunos ejemplos.
/abc
abc/
abc//xyz
La Clase CompositeName
La clase CompositeName
es la forma estructural de un nombre mixto. El constructor
acepta una representación string de un nombre mixto y lo divide en componentes
de acuerdo a la síntaxis de nombres mixtos.
Aquí hay un
ejemplo que usa el constructor para dividir un nombre mixto e imprimir sus
componentes.
String name = // Composite name to parse
try {
CompositeName cn = new CompositeName(name);
System.out.println(cn + " has " + cn.size() + " components: ");
for (int i = 0; i < cn.size(); i++) {
System.out.println(cn.get(i));
}
} catch (InvalidNameException e) {
System.out.println("Cannot parse name: " + name);
}
Al ejecutar este ejemplo con la entrada a/b/c se produce esta
salida.
a/b/c has 3 components.
a
b
c
La clase CompositeName contiene métodos para acceder a
componentes, para moficar un CompositeName, para comparar dos CompositeNames,
y para obtener la representación string de un CompositeName.
Acceder a los Componentes de un Nombre Mixto
Aquí están los métodos que podemos usar para acceder a los componentes de
un nombre compuesto.
Para recuperar el componente en una posición particular dentro de un CompositeName,
usamos get(). El ejemplo del constructor anterior mostraba un
ejemplo de este uso.
getAll() devuelve todos los componentes de un CompositeName
como una enumeration. Nos moveremos por la enumeration para
obtener cada componente. El ejemplo del constructor se pude reescribir
usando una enumeration, como se ve aquí.
try {
CompositeName cn = new CompositeName(name);
System.out.println(cn + " has " + cn.size() + " components: ");
for (Enumeration all = cn.getAll(); all.hasMoreElements();) {
System.out.println(all.nextElement());
}
} catch (InvalidNameException e) {
System.out.println("Cannot parse name: " + name);
}
También podemos obtener el sufijo o el prefijo de un CompositeName como
un ejemplar de CompositeName. Aquí hay un
ejemplo que obtiene los sufijos y prefijos de un nombre mixto.
CompositeName cn = new CompositeName("one/two/three");
Name suffix = cn.getSuffix(1); // 1 <= index < cn.size()
Name prefix = cn.getPrefix(1); // 0 <= index < 1
Cuando ejecutamos este programa, genera la siguiente salida.
two/three
one
Para hacer una copia de un CompositeName, usamos clone().
Modificar un Nombre Mixto
Aquí están los métodos que podemos usar para modificar un nombre mixto.
Después de crear un ejemplar de CompositeName, podemos
añadirle o eliminarle componentes. Aquí hay un
ejemplo que añade un CompositeName a otro ya existente,
añade componentes al principio y al final y elimina el segundo componente.
CompositeName cn = new CompositeName("1/2/3");
CompositeName cn2 = new CompositeName("4/5/6");
System.out.println(cn.addAll(cn2)); // 1/2/3/4/5/6
System.out.println(cn.add(0, "abc")); // abc/1/2/3/4/5/6
System.out.println(cn.add("xyz")); // abc/1/2/3/4/5/6/xyz
System.out.println(cn.remove(1)); // 1
System.out.println(cn); // abc/2/3/4/5/6/xyz
Comparar un Nombre Mixto
Aquí están los métodos que podemo usar para comparar dos nombres mixtos.
Podemos usar compareTo() para ordenar una lista de ejemplares de
CompositeName. Aquí hay un
ejemplo que usa compareTo() para implementar el algoritmo de
ordenación de la Burbuja.
private static void sort(CompositeName[] names) {
int bound = names.length-1;
CompositeName tmp;
while (true) {
int t = -1;
for (int j=0; j < bound; j++) {
int c = names[j].compareTo(names[j+1]);
if (c > 0) {
tmp = names[j];
names[j] = names[j+1];
names[j+1] = tmp;
t = j;
}
}
if (t == -1) break;
bound = t;
}
}
equals() nos permite determinar si dos CompositeNames
son sintácticamene iguales. Dos CompositeNames son iguales si
ambos tienen los mismos componentes (exactos, incluidas mayúsculas y
minúsculas) y en el mismo orden.
Con startsWith() y endsWith(), podemos
aprender si un CompositeName empieza o terminar con otro CompositeName;
es decir, si un CompositeName es un sufijo o un prefijo de otro CompositeName.
El método de conveniencia isEmpty() nos permite determinar
si un CompositeName tiene cero componentes. También podemos
usar la expresión size() == 0 para realizar el mismo chequeo.
Aquí tenemos ejemplos que usan
alguos de estos métodos de comparación.
CompositeName one = new CompositeName("cn=fs/o=JNDITutorial/tmp/a/b/c");
CompositeName two = new CompositeName("tmp/a/b/c");
CompositeName three = new CompositeName("cn=fs/o=JNDITutorial");
CompositeName four = new CompositeName();
System.out.println(one.equals(two)); // false
System.out.println(one.startsWith(three)); // true
System.out.println(one.endsWith(two)); // true
System.out.println(one.startsWith(four)); // true
System.out.println(one.endsWith(four)); // true
System.out.println(one.endsWith(three)); // false
System.out.println(one.isEmpty()); // false
System.out.println(four.isEmpty()); // true
System.out.println(four.size() == 0); // true
Obtener la Representación String
Aquí tenemos el método que podemos usar para obtener la representación string
de un nombre mixto.
toString()
Cuando usamos el constructor de CompositeName, le suministramos
una representación string de un nombre mixto y nos devuelve un ejemplar de CompositeName.
Para hacer la inversa, es decir, para obtener la representación string de un
ejemplar CompositeName, usamos toString(). El
resultado de este método se puede volver a enviar al constructor para producir
un nuevo ejemplar de CompositeName igual al original. Aquí
tenemos un ejemplo.
CompositeName cn = new CompositeName(name);
String str = cn.toString();
System.out.println(str);
CompositeName cn2 = new CompositeName(str);
System.out.println(cn.equals(cn2)); // true
CompositeName como argumento para Métodos de Context
Un ejemplar de CompositeName pasado como argumento a los
métodos de los interfaces Context
y DirContext
es tratado como un nombre mixto. Aquí tenemos un
ejemplo que localiza un objeto creando primero un ejemplar de CompositeName
que representa su nombre.
// Create the initial context
Context ctx = new InitialContext(env);
// Parse the string name into a CompositeName
Name cname = new CompositeName(
"cn=homedir,cn=Jon Ruiz,ou=people/tutorial/report.txt");
// Perform the lookup using the CompositeName
File f = (File) ctx.lookup(cname);