Construcci´on de caracter´ısticas
En esta secci´on se describir´a la API orientada a objetos basada en el lenguaje Java.
La primera parte de la API se relaciona con la construcci´on de carac- ter´ısticas. Para poder elegir entre las versiones regulares o normalizadas de las caracter´ısticas (ver la sem´antica de los programas FDL en el Cap´ıtu- lo 3), se usa un enfoque similar al patr´on Factory. Dos clases, RuleManager y FeatureDefinition, proveen m´etodos para construir caracter´ısticas. Los m´etodos de la clase RuleManager construir´an la forma regular o normal de la caracter´ıstica en base a un par´ametro.
Otro punto importante en la representaci´on es el uso de caracter´ısticas con nombre (comenzado en may´uscula). Como este tipo de caracter´ısticas
4.2. BIBLIOTECAS ORIENTADAS A OBJETOS 27 es usado en el programa FDL y durante el proceso de regularizaci´on y por lo tanto no es necesario en la representaci´on interna, se decidi´o no repre- sentar estas caracter´ısticas expl´ıcitamente, sobrecargando temporalmente el significado de las caracter´ısticas at´omicas.
La clase FeatureDefinition provee una operaci´on para reemplazar las caracter´ısticas con nombre.
public static Feature addFeature(Feature rootFeature,
Feature aFeature, AtomicFeature aNamedFeature) que se invoca para cada definici´on del programa FDL — el primer par´ametro (rootFeature) debe ser un objeto nulo para la caracter´ıstica principal, y para el resto de las caracter´ısticas, la instancia FDL a ser construida. El uso del m´etodo addFeature se puede observar en la Figura 4.2.
Los m´etodos de construcci´on usan adem´as el patr´on Composite (mostrado en la figura Figura 4.1 usando un diagrama conceptual de clases [RBP+91])
para representar las versiones regulares de las caracter´ısticas, o las reglas de normalizaci´on para representar la forma normal.
En el Composite, se usan listas de caracter´ısticas para expresar los argu- mentos de caracter´ısticas compuestas (Figura 4.1, parte (a)). Las restricciones se tratan de manera similar — ver Figura 4.3.
Representaci´on de la sem´antica
La regularizaci´on consiste simplemente en el reemplazo de las caracter´ısti- cas con nombre.
La normalizaci´on en cambio tiene que aplicar (doce) diferentes reglas para reducir caracter´ısticas duplicadas, desanidar, etc. Como ejemplo de im- plementaci´on para la normalizaci´on se eligi´o la quinta regla (presentada en la Cap´ıtulo 3). Esta regla normaliza caracter´ısticas all, sacando ocurrencias anidadas de all en sus argumentos. La clase RuleManager posee el m´etodo NormalizationRule5 que es invocado por el proceso que construye formas normales, cuando el usuario as´ı lo pide. El m´etodo toma la lista de carac- ter´ısticas que tiene los argumentos de un all, y verifica cada elemento, para ver si tiene una instancia de la clase all, en cuyo caso toma sus argumentos y los pone como argumentos del all que lo encierra — ver la Figura 4.4.
La clase RuleManager tiene adem´as m´etodos para realizar la expansi´on. Por ejemplo, el m´etodo que implementa la segunda regla de expansi´on se puede ver en la Figura 4.5. Todos los m´etodos para la expansi´on asumen que la caracter´ıstica est´a normalizada y dan un resultado en forma normal.
El paso final en la representaci´on de la sem´antica es la aplicaci´on de restricciones. Para ello, la caracter´ıstica en forma normal disyuntiva se pasa
Feature
AtomicFeature
OptionalFeature CompositeFeature
FeatrureList
OneOfFeature MoreOfFeature AllFeature
1..*
(a) Construcci´on de caracter´ısticas
Constraints Exclude - Feature : Feature Include - _feature : Feature Requires - _firstFeature : Feature - secondFeature : Feature Excludes - firstFeature : Feature - secondFeature : Feature (b) Restricciones
4.2. BIBLIOTECAS ORIENTADAS A OBJETOS 29
boolean norm = true;
// Esto se cambia para obtener una caracter´ıstica regular //Primera definici´on ->
// IODevice : all (opt(Printer), mouse, Display,
// opt(webcamera), keyboard, opt(microphone), opt(Receiver)) FeatureList ioList = new FeatureList(norm);
// opt(Printer)
Feature printerName = RuleManager.buildAtomicFeature("Printer");
Feature printerOpt =
RuleManager.buildOptionalFeature(printerName,norm);
ioList = RuleManager.buildFeatureList(ioList,printerOpt,norm); // mouse
Feature mouseAF = RuleManager.buildAtomicFeature("mouse"); ioList = RuleManager.buildFeatureList(ioList,mouseAF,norm);
// Display
Feature displayName = RuleManager.buildAtomicFeature("Display"); ioList = RuleManager.buildFeatureList(ioList,displayName,norm);
// opt(webcamera)
Feature webcamAF = RuleManager.buildAtomicFeature("webcamera"); Feature webcamOpt = RuleManager.buildOptionalFeature(webcamAF,norm); ioList = RuleManager.buildFeatureList(ioList,webcamOpt,norm); // keyboard Feature keyboardName = RuleManager.buildAtomicFeature("keyboard"); ioList = RuleManager.buildFeatureList(ioList,keyboardName,norm); // opt(microphone)
Feature micAF = RuleManager.buildAtomicFeature("microphone"); Feature micOpt = RuleManager.buildOptionalFeature(micAF,norm); ioList = RuleManager.buildFeatureList(ioList,micOpt,norm);
// opt(Receiver)
Feature recName = RuleManager.buildAtomicFeature("Receiver");
Feature recOpt =
RuleManager.buildOptionalFeature(recName,norm);
ioList = RuleManager.buildFeatureList(ioList,recOpt,norm); // IODevice : ...
Feature ioFeature = null;
Feature ioAllFeature =
RuleManager.buildAllFeature(ioList,norm);
ioFeature = FeatureDefinition.addFeature(ioFeature,ioAllFeature, (AtomicFeature)RuleManager.buildAtomicFeature("IODevice")); <...> Feature printerF = RuleManager.buildOptFeature(printerList,norm); ioFeature = FeatureDefinition.addFeature(ioFeature, printerF, (AtomicFeature)RuleManager.buildAtomicFeature("Printer")); <...> // Definici´on de restricciones
Vector cons = new Vector();
// constraint ->webcamera requires microphone
Constraint requiresCons = new Requires(webcamAF, micAF); cons.add(requiresCons);
// constraint ->include lcd
Constraint includeCons = new Include(lcdF); cons.add(includeCons);
<...>
System.out.println(FeatureSpec.printVersion(ioFeature,cons));
4.2. BIBLIOTECAS ORIENTADAS A OBJETOS 31
public static Feature NormalizationRule_5(FeatureList aFeature){ FeatureList tmpList = new FeatureList();
java.util.Enumeration tmpFeaturesEnumerator = aFeature.getFeatures().elements();
while (tmpFeaturesEnumerator.hasMoreElements()) { Object obj = tmpFeaturesEnumerator.nextElement(); if (obj instanceof AllFeature) {
java.util.Enumeration tmpSubFeaturesEnumerator = ((FeatureList)
((AllFeature) obj).getFeatures()).getFeatures().elements(); while (tmpSubFeaturesEnumerator.hasMoreElements())
tmpList = buildFeatureList(tmpList, (Feature)
tmpSubFeaturesEnumerator.nextElement(), true); }
else
tmpList = buildFeatureList(tmpList, (Feature) obj, true); }
return new AllFeature(tmpList); }
Figura 4.4: Implementaci´on de la quinta regla de normalizaci´on
public static Feature ExpansionRule_2(AllFeature f) { FeatureList fs1 = f.getFeatures(); OptionalFeature opt = (OptionalFeature)fs1.getOptionals().firstElement(); f.getFeatures().remove(opt); FeatureList fs2 = fs1.deepCopy(); f.getFeatures().add(opt.getFeature());
Feature g = RuleManager.buildAllFeature(fs2, normalized); FeatureList fs3 = new FeatureList(normalized);
fs3 = RuleManager.buildFeatureList(fs3,f, true); fs3 = RuleManager.buildFeatureList(fs3,g, true); return buildOneOfFeature(fs3, normalized); }
FeatureKind # getKind() : String + printVersion() : String - Header() : String - HeaderTop() : String # HeaderContent() : String - HeaderBottom() : String - Content() : String RegularFeature + RegularFeature() : RegularFeature # getKind() : String + HeaderContent() : String + getKind() : String NormalizedFeature + NormalizaedFeature() : NormalizedFeature # getKind() : String + getKind() : String # HeaderContent() : String ExpandedFeature + ExpandedFeature() : ExpandedFeature # getKind() : String + getKind() : String + HeaderContent() : String ConstrainedFeature + ConstrainedFeature() : ConstrainedFeature # getKind() : String + getKind() : String + HeaderContent() : String //método printVersion String tmpString = ""; tmpString = tmpString + Header(); tmpString = tmpString + Content(aFeature,aList); return tmpString; //método getKind return aFeature.fullExpand().applyList(aList).toString(); //método getKind return aFeature.fullExpand().toString(); //método getKind return aFeature.toString(); //método getKind return aFeature.toString(); FeatureSpec + printVersion() : String
Figura 4.6: Diagrama de clases para la impresi´on de instancias FDL
sucesivamente entre el conjunto de restricciones en forma de pipeline. Los argumentos de la caracter´ıstica expandida se van modificando al pasar de restricci´on en restricci´on. La caracter´ıstica devuelta por la ´ultima restricci´on es el resultado final.
Impresi´on de caracter´ısticas
La ´ultima funcionalidad de la API es obtener una representaci´on textual de una instancia espec´ıfica de FDL. Para construirla se usa el patr´on Templa- te method [GHJV95], por el cual se tiene una clase abstracta FeatureKind que define el m´etodo plantilla (template method) printVersion(), que usa otros m´etodos definidos en las subclases para construir la representaci´on final (por ejemplo, headerContent() y getKind() — ver la Figura 4.6).