/** * 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.dsl.converters; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import net.roboconf.core.dsl.ParsingConstants; import net.roboconf.core.dsl.parsing.AbstractBlock; import net.roboconf.core.dsl.parsing.BlockBlank; import net.roboconf.core.dsl.parsing.BlockComment; import net.roboconf.core.dsl.parsing.BlockInstanceOf; import net.roboconf.core.dsl.parsing.BlockProperty; import net.roboconf.core.dsl.parsing.FileDefinition; import net.roboconf.core.model.beans.Instance; import net.roboconf.core.utils.Utils; /** * To dump a collection of root {@link Instance}s into a file. * @author Vincent Zurczak - Linagora */ public class FromInstances { /** * Builds a file definition from a collection of instances. * @param rootInstances the root instances (not null) * @param targetFile the target file (will not be written) * @param addComment true to insert generated comments * @param saveRuntimeInformation true to save runtime information (such as IP...), false otherwise * @return a non-null file definition */ public FileDefinition buildFileDefinition( Collection<Instance> rootInstances, File targetFile, boolean addComment, boolean saveRuntimeInformation ) { FileDefinition result = new FileDefinition( targetFile ); result.setFileType( FileDefinition.INSTANCE ); if( addComment ) { String s = "# File created from an in-memory model,\n# without a binding to existing files."; BlockComment initialComment = new BlockComment( result, s ); result.getBlocks().add( initialComment ); result.getBlocks().add( new BlockBlank( result, "\n" )); } for( Instance rootInstance : rootInstances ) result.getBlocks().addAll( buildInstanceOf( result, rootInstance, addComment, saveRuntimeInformation )); return result; } private Collection<AbstractBlock> buildInstanceOf( FileDefinition file, Instance rootInstance, boolean addComment, boolean saveRuntimeInformation ) { Collection<AbstractBlock> result = new ArrayList<> (); // Process the root instance Map<Instance,BlockInstanceOf> instanceToBlock = new LinkedHashMap<> (); BlockInstanceOf rootBlock = new BlockInstanceOf( file ); instanceToBlock.put( rootInstance, rootBlock ); List<Instance> toProcess = new ArrayList<> (); toProcess.add( rootInstance ); while( ! toProcess.isEmpty()) { // Process the current instance Instance instance = toProcess.remove( 0 ); BlockInstanceOf currentBlock = instanceToBlock.get( instance ); currentBlock.setName( instance.getComponent().getName()); BlockProperty p; if( ! Utils.isEmptyOrWhitespaces( instance.getName())) { p = new BlockProperty( file, ParsingConstants.PROPERTY_INSTANCE_NAME, instance.getName()); currentBlock.getInnerBlocks().add( p ); } if( ! instance.channels.isEmpty()) { String s = Utils.format( instance.channels, ", " ); p = new BlockProperty( file, ParsingConstants.PROPERTY_INSTANCE_CHANNELS, s ); currentBlock.getInnerBlocks().add( p ); } for( Map.Entry<String,String> export : instance.overriddenExports.entrySet()) { p = new BlockProperty( file, export.getKey(), export.getValue()); currentBlock.getInnerBlocks().add( p ); } // Runtime information if( saveRuntimeInformation ) { p = new BlockProperty( file, ParsingConstants.PROPERTY_INSTANCE_STATE, instance.getStatus().toString()); currentBlock.getInnerBlocks().add( p ); StringBuilder sb = new StringBuilder(); for( Iterator<Map.Entry<String,String>> it = instance.data.entrySet().iterator(); it.hasNext(); ) { Map.Entry<String,String> entry = it.next(); sb.append( entry.getKey()); sb.append( " = " ); sb.append( entry.getValue()); if( it.hasNext()) sb.append( ", " ); } if( sb.length() > 0 ) { p = new BlockProperty( file, ParsingConstants.PROPERTY_INSTANCE_DATA, sb.toString()); currentBlock.getInnerBlocks().add( p ); } } // Update the parent BlockInstanceOf parentBlock = instanceToBlock.get( instance.getParent()); if( parentBlock != null ) { parentBlock.getInnerBlocks().add( new BlockBlank( file, "" )); parentBlock.getInnerBlocks().add( currentBlock ); } // Children for( Instance child : instance.getChildren()) { instanceToBlock.put( child, new BlockInstanceOf( file )); toProcess.add( child ); } } // Add the root instance to the result result.add( rootBlock ); result.add( new BlockBlank( file, "\n" )); return result; } }