/****************************************************************************** * Copyright (c) 2012, Linagora * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Linagora - initial API and implementation *******************************************************************************/ package com.ebmwebsourcing.petals.studio.dev.properties.internal; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import com.ebmwebsourcing.petals.studio.dev.properties.AbstractModel; /** * @author Vincent Zurczak - Linagora */ public class AbstractModelValidator { private static final String MARKER_ID = "com.ebmwebsourcing.petals.studio.dev.properties.markers"; /** * Validates a properties model file. * @param propertiesFile */ public static void validateAndMark( IFile propertiesFile ) { // Clear the markers clearMarkers( propertiesFile ); // Load the current file content and get the property lines Map<String, Integer> propertyToLine = new HashMap<String, Integer>(); ByteArrayOutputStream os = new ByteArrayOutputStream(); File file = propertiesFile.getLocation().toFile(); try { Utils.copyStream( file, os ); int currentLine = 0; char lastChar = 'c'; for( String line : os.toString( "UTF-8" ).split( "\n" ) ) { currentLine++; line = line.trim(); // Eliminate some cases if( line.startsWith( "#" ) ) continue; if( line.isEmpty() ) continue; if( lastChar == '\\' ) { lastChar = 'c'; continue; } int index = line.indexOf( '=' ); if( index < 0 ) continue; // Now, we have a good candidate String property = line.substring( 0, index ).trim(); propertyToLine.put( property, currentLine ); // Prepare next iteration lastChar = line.charAt( line.length() - 1 ); } } catch( IOException e ) { PetalsStudioDevPlugin.log( e, IStatus.ERROR ); return; } // Load and validate the model try { AbstractModel model = new AbstractModel( file ); for( String key : model.getProperties().getPropertyMap().keySet()) { Integer line = propertyToLine.get( key ); if( line == null ) { PetalsStudioDevPlugin.log( key + " property was not indexed correctly.", IStatus.ERROR ); line = 1; } if( model.findTypeDeclaration( key ) == null ) createMarker( propertiesFile, "No type defined for '" + key + "'. Assumption: string.", line, false ); } // Otherwise, check it is correctly defined for( Map.Entry<String,List<String>> entry : model.validateAbstractModel().entrySet()) { Integer line = entry.getKey().isEmpty() ? 1 : propertyToLine.get( entry.getKey()); if( line == null ) { PetalsStudioDevPlugin.log( entry.getKey() + " property was not indexed correctly.", IStatus.ERROR ); line = 1; } for( String error :entry.getValue()) createMarker( propertiesFile, error, line, true ); } } catch( IOException e ) { createMarker( propertiesFile, "The file could not be loaded.", 1, true ); } } /** * Validates a properties model file. * @param propertiesFile */ public static boolean validate( IFile propertiesFile ) { boolean valid; try { AbstractModel model = new AbstractModel( propertiesFile.getLocation().toFile()); valid = validate( model ); } catch( IOException e ) { PetalsStudioDevPlugin.log( e, IStatus.ERROR ); valid = false; } return valid; } /** * Validates a properties model file. * @param model */ public static boolean validate( AbstractModel model ) { return model.validateAbstractModel().isEmpty(); } /** * Clears all the markers. * @param propertiesFile */ public static void clearMarkers( IFile propertiesFile ) { try { propertiesFile.deleteMarkers( MARKER_ID, true, IResource.DEPTH_ONE ); } catch( CoreException e ) { PetalsStudioDevPlugin.log( e, IStatus.ERROR ); } } /** * Creates a marker. * @param propertiesFile * @param message a message (not null) * @param line a line number * @param error true if it is an error, false for a warning */ private static void createMarker( IFile propertiesFile, String message, int line, boolean error ) { try { IMarker marker = propertiesFile.createMarker( MARKER_ID ); marker.setAttribute( IMarker.SEVERITY, error ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING ); marker.setAttribute( IMarker.LINE_NUMBER, line ); marker.setAttribute( IMarker.MESSAGE, message ); } catch( CoreException e ) { PetalsStudioDevPlugin.log( e, IStatus.ERROR ); } } }