/** * Copyright 2014-2017 Linagora, Université Joseph Fourier, Floralis * * The present code is developed in the scope of the joint LINAGORA - * Université Joseph Fourier - Floralis research program and is designated * as a "Result" pursuant to the terms and conditions of the LINAGORA * - Université Joseph Fourier - Floralis research program. Each copyright * holder of Results enumerated here above fully & independently holds complete * ownership of the complete Intellectual Property rights applicable to the whole * of said Results, and may freely exploit it in any manner which does not infringe * the moral rights of the other copyright holders. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.roboconf.core.internal.dsl.parsing; import java.util.Iterator; import net.roboconf.core.dsl.ParsingConstants; import net.roboconf.core.dsl.ParsingModelValidator; import net.roboconf.core.dsl.parsing.AbstractBlock; import net.roboconf.core.dsl.parsing.AbstractBlockHolder; import net.roboconf.core.dsl.parsing.BlockBlank; import net.roboconf.core.dsl.parsing.BlockComment; import net.roboconf.core.dsl.parsing.BlockComponent; import net.roboconf.core.dsl.parsing.BlockFacet; import net.roboconf.core.dsl.parsing.BlockImport; import net.roboconf.core.dsl.parsing.BlockInstanceOf; import net.roboconf.core.dsl.parsing.BlockProperty; import net.roboconf.core.dsl.parsing.FileDefinition; /** * A class to serialize a relations model. * @author Vincent Zurczak - Linagora */ public class FileDefinitionSerializer { private String lineSeparator = System.getProperty( "line.separator" ); /** * Constructor. */ public FileDefinitionSerializer() { // nothing } /** * Constructor. * @param lineSeparator the line separator (ignored if null) */ public FileDefinitionSerializer( String lineSeparator ) { if( lineSeparator != null ) this.lineSeparator = lineSeparator; } /** * @param definitionFile the relations file * @param writeComments true to write comments * @return a string (never null) */ public String write( FileDefinition definitionFile, boolean writeComments ) { StringBuilder sb = new StringBuilder(); for( Iterator<AbstractBlock> it = definitionFile.getBlocks().iterator(); it.hasNext(); ) { sb.append( write( it.next(), writeComments )); if( it.hasNext()) sb.append( this.lineSeparator ); } return sb.toString(); } /** * @param block a block * @param writeComments true to write comments * @return a string (never null) */ public String write( AbstractBlock block, boolean writeComments ) { String result = null; switch( block.getInstructionType()) { case AbstractBlock.COMPONENT: result = write((BlockComponent) block, writeComments ); break; case AbstractBlock.FACET: result = write((BlockFacet) block, writeComments ); break; case AbstractBlock.INSTANCEOF: result = write((BlockInstanceOf) block, writeComments, 0 ); break; case AbstractBlock.IMPORT: result = write((BlockImport) block, writeComments ); break; case AbstractBlock.PROPERTY: result = write((BlockProperty) block, writeComments ); break; case AbstractBlock.COMMENT: result = write((BlockComment) block, writeComments ); break; case AbstractBlock.BLANK: result = write((BlockBlank) block, writeComments ); break; default: break; } return result; } /** * @param block a block * @param writeComments true to write comments * @return a string (never null) */ public String write( BlockImport block, boolean writeComments ) { StringBuilder sb = new StringBuilder(); sb.append( "import " ); sb.append( block.getUri()); sb.append( ";" ); if( writeComments && block.getInlineComment() != null ) sb.append( block.getInlineComment()); return sb.toString(); } /** * @param block a block * @param writeComments true to write comments * @return a string (never null) */ public String write( BlockComponent block, boolean writeComments ) { return writePropertiesHolder( block, writeComments, 0 ); } /** * @param block a block * @param writeComments true to write comments * @return a string (never null) */ public String write( BlockFacet block, boolean writeComments ) { return ParsingConstants.KEYWORD_FACET + " " + writePropertiesHolder( block, writeComments, 0 ); } /** * @param block a block * @param writeComments true to write comments * @param indentationLevel the indentation level * @return a string (never null) */ public String write( BlockInstanceOf block, boolean writeComments, int indentationLevel ) { StringBuilder sb = new StringBuilder(); indent( sb, indentationLevel ); sb.append( ParsingConstants.KEYWORD_INSTANCE_OF ); sb.append( " " ); sb.append( writePropertiesHolder( block, writeComments, indentationLevel )); return sb.toString(); } /** * @param block a block * @param writeComments true to write comments * @return a string (never null) */ public String write( BlockBlank block, boolean writeComments ) { StringBuilder sb = new StringBuilder(); // Invalid blank sections can be "repaired" even if they are invalid. // Here, we replace it by a line break. // The error is signaled as a warning in the validation. // Useful if a blank section was built programmatically. if( ParsingModelValidator.validate( block ).isEmpty()) sb.append( block.getContent()); else sb.append( this.lineSeparator ); return sb.toString(); } /** * @param block a block * @param writeComments true to write comments * @return a string (never null) */ public String write( BlockProperty block, boolean writeComments ) { StringBuilder sb = new StringBuilder(); sb.append( block.getName()); sb.append( ": " ); sb.append( block.getValue()); sb.append( ";" ); if( writeComments && block.getInlineComment() != null ) sb.append( block.getInlineComment()); return sb.toString(); } /** * @param block a block * @param writeComments true to write comments * @return a string (never null) */ public String write( BlockComment block, boolean writeComments ) { StringBuilder sb = new StringBuilder(); if( writeComments ) { // Invalid comment sections can be "repaired" even if they are invalid. // Here, we insert a comment delimiter where needed. // The error is signaled as a warning in the validation. // Useful if a comment was built programmatically. if( ParsingModelValidator.validate( block ).isEmpty()) { sb.append( block.getContent()); } else { for( String s : block.getContent().split( "\n" )) { if( ! s.trim().startsWith( ParsingConstants.COMMENT_DELIMITER )) sb.append( "# " ); sb.append( s ); sb.append( this.lineSeparator ); } } } return sb.toString(); } /** * @param holder a block * @param writeComments true to write comments * @param indentationLevel the indentation level * @return a string (never null) */ private String writePropertiesHolder( AbstractBlockHolder holder, boolean writeComments, int indentationLevel ) { StringBuilder sb = new StringBuilder(); sb.append( holder.getName()); sb.append( " {" ); if( writeComments && holder.getInlineComment() != null ) sb.append( holder.getInlineComment()); for( AbstractBlock block : holder.getInnerBlocks()) { sb.append( this.lineSeparator ); if( block.getInstructionType() == AbstractBlock.INSTANCEOF ) { sb.append( write((BlockInstanceOf) block, writeComments, indentationLevel + 1 )); } else { if( block.getInstructionType() == AbstractBlock.PROPERTY ) indent( sb, indentationLevel + 1 ); sb.append( write( block, writeComments )); } } sb.append( this.lineSeparator ); indent( sb, indentationLevel ); sb.append( "}" ); if( writeComments && holder.getClosingInlineComment() != null ) sb.append( holder.getClosingInlineComment()); return sb.toString(); } /** * @param sb * @param indentationLevel */ private void indent( StringBuilder sb, int indentationLevel ) { for( int i=0; i<indentationLevel; i++ ) sb.append( "\t" ); } }