Java tutorial
/*<Dynamic Refactoring Plugin For Eclipse 2.0 - Plugin that allows to perform refactorings on Java code within Eclipse, as well as to dynamically create and manage new refactorings> Copyright (C) 2009 Laura Fuente De La Fuente This file is part of Foobar Foobar is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.*/ package dynamicrefactoring.domain.xml.writer; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; import org.jdom.DocType; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.input.SAXBuilder; import org.jdom.output.Format; import org.jdom.output.XMLOutputter; import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableListMultimap.Builder; import dynamicrefactoring.RefactoringConstants; import dynamicrefactoring.RefactoringPlugin; import dynamicrefactoring.domain.DynamicRefactoringDefinition; import dynamicrefactoring.domain.InputParameter; import dynamicrefactoring.domain.RefactoringExample; import dynamicrefactoring.domain.RefactoringMechanismInstance; import dynamicrefactoring.domain.RefactoringMechanismType; import dynamicrefactoring.domain.Scope; import dynamicrefactoring.domain.metadata.interfaces.Category; import dynamicrefactoring.domain.xml.reader.XMLRefactoringReaderException; import dynamicrefactoring.domain.xml.reader.XMLRefactoringReaderImp; import dynamicrefactoring.util.PluginStringUtils; /** * Utiliza la implementacin basada en JDOM para escribir los ficheros XML de * refactorizaciones dinmicas. * * @author <A HREF="mailto:lfd0002@alu.ubu.es">Laura Fuente de la Fuente</A> * @author <A HREF="mailto:alc0022@alu.ubu.es">?ngel Lpez Campo</A> * @author <A HREF="mailto:epf0006@alu.ubu.es">Eduardo Pea Fernndez</A> * @author <A HREF="mailto:sfd0009@alu.ubu.es">Sonia Fuente de la Fuente</A> * @author <A HREF="mailto:ehp0001@alu.ubu.es">Enrique Herrero Paredes</A> */ public final class JDOMXMLRefactoringWriterImp implements XMLRefactoringWriterImp { /** * La definicin de refactorizacin que se debe escribir. */ private DynamicRefactoringDefinition refactoringDefinition; /** * Constructor. * * @param refactoringDefinition * definicin de la refactorizacin que se debe escribir. */ public JDOMXMLRefactoringWriterImp(DynamicRefactoringDefinition refactoringDefinition) { this.refactoringDefinition = refactoringDefinition; initializeFormat(); } /** * Genera el documento de JDOM que representa la refactorizacion. * * @return documento de jdom con la representacion de la refactorizacion */ @Override public Document getDocumentOfRefactoring() { Element refactoring = new Element(XMLRefactoringReaderImp.REFACTORING_TAG); DocType type = new DocType(refactoring.getName(), "refactoringDTD.dtd"); //$NON-NLS-1$ refactoring.setAttribute("name", refactoringDefinition.getName()); //$NON-NLS-1$ constructRefactoringInformation(refactoring); constructRefactoringInputs(refactoring); constructRefactoringMechanism(refactoring); constructRefactoringExamples(refactoring); return new Document(refactoring, type); } /** * Cambia el nombre de una refactorinzacin en el fichero temporal que * alamacena las refactorizaciones segn el ambito al que pertenece su * entrada principal. * * @param scope * ambito de la refactorizacin. * @param newName * nuevo nombre. * @param originalName * nombre anterior. * @throws XMLRefactoringReaderException * XMLRefactoringReaderException. */ public void renameRefactoringIntoXml(Scope scope, String newName, String originalName) throws XMLRefactoringReaderException { String path = RefactoringPlugin.getDynamicRefactoringsDir() + "/" + newName + "/" + newName + ".xml"; try { SAXBuilder builder = new SAXBuilder(true); builder.setIgnoringElementContentWhitespace(true); Document doc = builder.build(new File(RefactoringConstants.REFACTORING_TYPES_FILE).toURI().toString()); Element root = doc.getRootElement(); // Renombramos el elemento Element elementDef = root.getChild(scope.getXmlTag()); for (int i = 0; i < elementDef.getChildren().size(); i++) { Element refactor = (Element) elementDef.getChildren().get(i); if (refactor.getAttribute("name").getValue().equals(originalName)) { refactor.getAttribute("name").setValue(newName); refactor.getAttribute("path").setValue(path); break; } } writeToFile(RefactoringConstants.REFACTORING_TYPES_FILE, doc); } catch (JDOMException jdomexception) { throw new XMLRefactoringReaderException(jdomexception.getMessage()); } catch (IOException ioexception) { throw new XMLRefactoringReaderException(ioexception.getMessage()); } } /** * Escribe el fichero XML a partir de la definicin de la refactorizacin. * * @param dir * directorio donde se guardar el fichero. * * @throws XMLRefactoringWriterException * si se produce un error al intentar almacenar la definicin de * la refactorizacin en el fichero. */ @Override public void writeRefactoring(File dir) throws XMLRefactoringWriterException { try { writeToFile(dir.getPath() + File.separatorChar + refactoringDefinition.getName() + //$NON-NLS-1$ RefactoringConstants.FILE_EXTENSION, getDocumentOfRefactoring()); } catch (Exception e) { throw new XMLRefactoringWriterException(e.getMessage()); } } /** * Escribe los elementos con la informacin general de la refactorizacin. * * <p> * Almacena la descripcin bsica de la refactorizacin, la ruta de la * imagen asociada a la refactorizacin y la motivacin de la misma. * </p> * * @param refactoringElement * el elemento XML raz a partir del cual se aadir el elemento * hijo con la informacin bsica de la refactorizacin. */ private void constructRefactoringInformation(Element refactoringElement) { Element information = new Element(XMLRefactoringReaderImp.INFORMATION_ELEMENT); if (refactoringDefinition.getDescription().length() != 0) { Element description = new Element(XMLRefactoringReaderImp.DESCRIPTION_ELEMENT); description.setText(refactoringDefinition.getDescription()); information.addContent(description); } // En el DTD se especifica que la imagen es requerida; // mejor que no lo sea. if (refactoringDefinition.getImage().length() != 0) { Element image = new Element(XMLRefactoringReaderImp.IMAGE_ELEMENT); image.setAttribute("src", refactoringDefinition.getImage()); //$NON-NLS-1$ information.addContent(image); } if (refactoringDefinition.getMotivation().length() != 0) { Element motivation = new Element(XMLRefactoringReaderImp.MOTIVATION_ELEMENT); motivation.setText(refactoringDefinition.getMotivation()); information.addContent(motivation); } // Agrega las palabras clave que describen la refactorizacion if (refactoringDefinition.getKeywords().size() > 0) { Element keywordsElement = createKeywordsElement(); information.addContent(keywordsElement); } // Agrega las categorias a las que pertence la refactorizacion if (refactoringDefinition.getCategories().size() > 0) { Element categorizationElement = createCategorizationElement(createCategoriesMapByParent()); information.addContent(categorizationElement); } refactoringElement.addContent(information); } /** * Crea el elemento xml con la lista de palabras clave de la * refactorizacion. * * @return elemento xml con la lista de palabras clave de la refactorizacion */ private Element createKeywordsElement() { Element keywordsElement = new Element(XMLRefactoringReaderImp.KEYWORDS_ELEMENT); for (String keyword : refactoringDefinition.getKeywords()) { Element keywordElem = new Element(XMLRefactoringReaderImp.KEYWORD_ELEMENT); keywordElem.setText(keyword); keywordsElement.addContent(keywordElem); } return keywordsElement; } /** * Crea el elemento categorization que contiene las categorias a las que * pertenece una refactorizacion dentro de las clasificaciones existentes. * * @param categoriesMapByParent * mapa que contiene como claves los nombres de las * clasificaciones y como valores las categorias a las que la * refactorizacion pertenece en esa clasificacion * @return elemento de jdom con la categorizacion de la refactorizacion */ private Element createCategorizationElement(ImmutableListMultimap<String, Category> categoriesMapByParent) { Element categorizationElement = new Element(XMLRefactoringReaderImp.CATEGORIZATION_ELEMENT); for (String classificationName : categoriesMapByParent.keySet()) { Element classificationElement = new Element(XMLRefactoringReaderImp.CLASSIFICATION_ELEMENT); classificationElement.setAttribute(XMLRefactoringReaderImp.CLASSIFICATION_NAME_ATTRIBUTE, classificationName); for (Category c : categoriesMapByParent.get(classificationName)) { Element categoryElement = new Element(XMLRefactoringReaderImp.CATEGORY_ELEMENT); categoryElement.addContent(c.getName()); classificationElement.addContent(categoryElement); } categorizationElement.addContent(classificationElement); } return categorizationElement; } /** * Crea un mapa que contiene como claves los nombres de las clasificaciones * y como valores las categorias a las que la refactorizacion pertenece en * esa clasificacion. * * @return mapa que contiene como claves los nombres de las clasificaciones * y como valores las categorias a las que la refactorizacion * pertenece en esa clasificacion */ private ImmutableListMultimap<String, Category> createCategoriesMapByParent() { Builder<String, Category> builder = new ImmutableListMultimap.Builder<String, Category>(); for (Category c : refactoringDefinition.getCategories()) { builder.put(c.getParent(), c); } ImmutableListMultimap<String, Category> categoriesMapByParent = builder.build(); return categoriesMapByParent; } /** * Escribe los elementos de las entradas de la refactorizacin. * * @param refactoringElement * el elemento XML raz a partir del cual se aadir el elemento * hijo con la informacin acerca de las entradas de la * refactorizacin. */ private void constructRefactoringInputs(Element refactoringElement) { Element inputs = new Element(XMLRefactoringReaderImp.INPUTS_ELEMENT); for (InputParameter inputDefinition : refactoringDefinition.getInputs()) { Element input = new Element(XMLRefactoringReaderImp.INPUT_ELEMENT); input.setAttribute(XMLRefactoringReaderImp.TYPE_INPUT_ATTRIBUTE, inputDefinition.getType()); if (inputDefinition.getName().length() != 0) input.setAttribute(XMLRefactoringReaderImp.NAME_INPUT_ATTRIBUTE, inputDefinition.getName()); if (inputDefinition.getFrom() != null && inputDefinition.getFrom().length() != 0) input.setAttribute(XMLRefactoringReaderImp.FROM_INPUT_ATTRIBUTE, inputDefinition.getFrom()); if (inputDefinition.getMethod() != null && inputDefinition.getMethod().length() != 0) input.setAttribute(XMLRefactoringReaderImp.METHOD_INPUT_ATTRIBUTE, inputDefinition.getMethod()); input.setAttribute(XMLRefactoringReaderImp.ROOT_INPUT_ATTRIBUTE, String.valueOf(inputDefinition.isMain())); inputs.addContent(input); } refactoringElement.addContent(inputs); } /** * Escribe los elementos correspondientes a los predicados y acciones que * componen la refactorizacin. * * @param refactoringElement * el elemento XML raz a partir del cual se aadir el elemento * hijo con la informacin acerca de los predicados y las * acciones que componen la refactorizacin. */ private void constructRefactoringMechanism(Element refactoringElement) { Element mechanism = new Element(XMLRefactoringReaderImp.MECHANISM_ELEMENT); mechanism.addContent(createMechanismElement(RefactoringMechanismType.PRECONDITION, XMLRefactoringReaderImp.PRECONDITIONS_ELEMENT, XMLRefactoringReaderImp.PRECONDITION_ELEMENT, refactoringDefinition.getPreconditions())); mechanism.addContent( createMechanismElement(RefactoringMechanismType.ACTION, XMLRefactoringReaderImp.ACTIONS_ELEMENT, XMLRefactoringReaderImp.ACTION_ELEMENT, refactoringDefinition.getActions())); mechanism.addContent(createMechanismElement(RefactoringMechanismType.POSTCONDITION, XMLRefactoringReaderImp.POSTCONDITIONS_ELEMENT, XMLRefactoringReaderImp.POSTCONDITION_ELEMENT, refactoringDefinition.getPostconditions())); refactoringElement.addContent(mechanism); } /** * Crea los mecanismos de una refactorizacion. * * @param type * tipo del mecanismo * @param parentTagName * nombre de la etiqueta padre * @param childTagName * nombre de la etiqueta hijo * @param mechanismElements * mecanismos a crear * @return elemento con todos los mecanismos creados */ private Element createMechanismElement(RefactoringMechanismType type, String parentTagName, String childTagName, List<RefactoringMechanismInstance> mechanismElements) { Element mechanismElement = new Element(parentTagName); for (final RefactoringMechanismInstance mechanism : mechanismElements) { final Element childElement = new Element(childTagName); childElement.setAttribute(XMLRefactoringReaderImp.NAME_ATTRIBUTE, PluginStringUtils.getMechanismFullyQualifiedName(type, mechanism.getClassName())); constructAmbiguousParameters(childElement, mechanism, type); mechanismElement.addContent(childElement); } return mechanismElement; } /** * Escribe los elementos de los parmetros ambiguos de la refactorizacin. * * @param partOfRefactoring * el elemento de parmetros ambiguos. * @param nameOfPart * el elemento del nombre del parmetro ambiguo. * @param typeOfPart * el elemento del tipo del parmetro ambiguo. */ private void constructAmbiguousParameters(Element partOfRefactoring, RefactoringMechanismInstance nameOfPart, RefactoringMechanismType typeOfPart) { for (String ambiguousParameter : nameOfPart.getInputParameters()) { Element param = new Element(XMLRefactoringReaderImp.PARAM_ELEMENT); param.setAttribute(XMLRefactoringReaderImp.NAME_PARAM_ATTRIBUTE, ambiguousParameter); partOfRefactoring.addContent(param); } } /** * Escribe los elementos de los ejemplos de la refactorizacin. * * @param refactoringElement * el elemento XML raz a partir del cual se aadir el elemento * hijo con la informacin acerca de los ejemplos asociados a la * refactorizacin. */ private void constructRefactoringExamples(Element refactoringElement) { Element examples = new Element(XMLRefactoringReaderImp.EXAMPLES_ELEMENT); for (RefactoringExample ex : refactoringDefinition.getExamples()) { if (!(ex.getBefore().isEmpty() && ex.getAfter().isEmpty())) { Element example = new Element(XMLRefactoringReaderImp.EXAMPLE_ELEMENT); example.setAttribute(XMLRefactoringReaderImp.BEFORE_EXAMPLE_ATTRIBUTE, ex.getBefore()); example.setAttribute(XMLRefactoringReaderImp.AFTER_EXAMPLE_ATTRIBUTE, ex.getAfter()); examples.addContent(example); } } refactoringElement.addContent(examples); } /** * Escribe los datos del documento XML en el fichero indicado. * * @param fname * el nombre del fichero. * @param doc * el documento XML. * * @throws IOException * si se produce un error de lectura escritura al trasladar los * datos del documento XML al fichero. */ private static void writeToFile(String fname, Document doc) throws IOException { FileOutputStream out = new FileOutputStream(fname); XMLOutputter op = new XMLOutputter(initializeFormat()); op.output(doc, out); out.flush(); out.close(); } /** * Inicializa las opciones de formato del fichero XML. * * @return devuelve el formato que se da al fichero XML */ private static Format initializeFormat() { Format format = Format.getPrettyFormat(); format.setIndent("\t"); //$NON-NLS-1$ format.setLineSeparator("\n"); //$NON-NLS-1$ format.setExpandEmptyElements(false); format.setEncoding("ISO-8859-1"); //$NON-NLS-1$ return format; } }