/******************************************************************************* * This file is part of Goko. * * Goko 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. * * Goko 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 Goko. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ package org.goko.core.rs274ngcv3.parser.advanced; import java.util.ArrayList; import java.util.List; import org.apache.commons.collections.CollectionUtils; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.SubMonitor; import org.goko.core.common.exception.GkException; import org.goko.core.common.exception.GkTechnicalException; import org.goko.core.gcode.bean.GCodeCommand; import org.goko.core.gcode.bean.GCodeContext; import org.goko.core.gcode.bean.GCodeFile; import org.goko.core.log.GkLog; import org.goko.core.rs274ngcv3.parser.GCodeToken; import org.goko.core.rs274ngcv3.parser.GCodeTokenType; import org.goko.core.rs274ngcv3.parser.ModalGroup; import org.goko.core.rs274ngcv3.parser.advanced.builders.ArcCommandBuilder; import org.goko.core.rs274ngcv3.parser.advanced.builders.CommentCommandBuilder; import org.goko.core.rs274ngcv3.parser.advanced.builders.FunctionCommandBuilder; import org.goko.core.rs274ngcv3.parser.advanced.builders.LinearCommandBuilder; import org.goko.core.rs274ngcv3.parser.advanced.builders.RawCommandBuilder; import org.goko.core.rs274ngcv3.parser.advanced.builders.SettingCommandBuilder; public class AdvancedGCodeAnalyser { private static final GkLog LOG = GkLog.getLogger(AdvancedGCodeAnalyser.class); private List<IRS274CommandBuilder<?>> lstBuilders; private List<ModalGroup> modalGroups; public AdvancedGCodeAnalyser() { lstBuilders = new ArrayList<IRS274CommandBuilder<?>>(); lstBuilders.add( new ArcCommandBuilder() ); lstBuilders.add( new LinearCommandBuilder() ); //lstBuilders.add( new ToolChangeCommandBuilder() ); lstBuilders.add( new FunctionCommandBuilder() ); lstBuilders.add( new SettingCommandBuilder() ); lstBuilders.add( new CommentCommandBuilder() ); lstBuilders.add( new RawCommandBuilder() ); initializeModalGroups(); } protected void initializeModalGroups(){ this.modalGroups = new ArrayList<ModalGroup>(); this.modalGroups.add( new ModalGroup("G0", "G1", "G2", "G3", "G38.2", "G80", "G81", "G82", "G83", "G84", "G85", "G86", "G87", "G88", "G89" )); this.modalGroups.add( new ModalGroup("G17", "G18", "G19" )); this.modalGroups.add( new ModalGroup("G90", "G91")); this.modalGroups.add( new ModalGroup("G93", "G94")); this.modalGroups.add( new ModalGroup("G20", "G21")); this.modalGroups.add( new ModalGroup("G40", "G41", "G42")); this.modalGroups.add( new ModalGroup("G43","G49")); this.modalGroups.add( new ModalGroup("G98","G99")); this.modalGroups.add( new ModalGroup("G54", "G55", "G56", "G57", "G58", "G59", "G59.1", "G59.2", "G59.3")); this.modalGroups.add( new ModalGroup("G61", "G61.1", "G64")); this.modalGroups.add( new ModalGroup("M0", "M1", "M2", "M30", "M60")); this.modalGroups.add( new ModalGroup("M6")); this.modalGroups.add( new ModalGroup("M3","M4","M5")); this.modalGroups.add( new ModalGroup("M7","M9")); this.modalGroups.add( new ModalGroup("M8","M9")); this.modalGroups.add( new ModalGroup("M48", "M49")); } /** * Create a GCodeFile by parsing the given list of {@link GCodeToken} * @param tokens the list of token * @param intialContext the initial context * @return a {@link GCodeFile} * @throws GkException GkException */ public GCodeFile createFile(List<GCodeToken> tokens, GCodeContext intialContext) throws GkException{ GCodeContext context = new GCodeContext(intialContext); List<GCodeToken> lineTokens = new ArrayList<GCodeToken>(); List<GCodeCommand> lstCommmands = new ArrayList<GCodeCommand>(); // Let's detect the end token. We search the first NEW_LINE token, or the end of the list for (GCodeToken gCodeToken : tokens) { if(gCodeToken.getType() == GCodeTokenType.NEW_LINE){ if(CollectionUtils.isNotEmpty(lineTokens)){ GCodeCommand command = createCommand(lineTokens, context); lstCommmands.add( command ); lineTokens.clear(); } }else{ lineTokens.add(gCodeToken); } } // Let's compute the final GCodeCommand if(CollectionUtils.isNotEmpty(lineTokens)){ GCodeCommand command = createCommand(lineTokens, context); lstCommmands.add( command ); lineTokens.clear(); } GCodeFile file = new GCodeFile(lstCommmands); return file; } public GCodeFile createFile(List<GCodeToken> tokens, GCodeContext intialContext, IProgressMonitor monitor) throws GkException{ GCodeContext context = new GCodeContext(intialContext); List<GCodeToken> lineTokens = new ArrayList<GCodeToken>(); List<GCodeCommand> lstCommmands = new ArrayList<GCodeCommand>(); // Let's detect the end token. We search the first NEW_LINE token, or the end of the list SubMonitor progress = SubMonitor.convert(monitor, tokens.size()); for (GCodeToken gCodeToken : tokens) { if(gCodeToken.getType() == GCodeTokenType.NEW_LINE){ if(CollectionUtils.isNotEmpty(lineTokens)){ GCodeCommand command = createCommand(lineTokens, context); lstCommmands.add( command ); lineTokens.clear(); } }else{ lineTokens.add(gCodeToken); } progress.worked(1); } // Let's compute the final GCodeCommand if(CollectionUtils.isNotEmpty(lineTokens)){ GCodeCommand command = createCommand(lineTokens, context); lstCommmands.add( command ); lineTokens.clear(); } GCodeFile file = new GCodeFile(lstCommmands); return file; } /** * Create a GCodeCommand from the given list of tokens * @param tokens the list of token * @param intialContext the initial context * @return a {@link GCodeCommand} * @throws GkException GkException */ public GCodeCommand createCommand(List<GCodeToken> tokens, GCodeContext intialContext) throws GkException{ verifyModality(tokens); GCodeCommand typedCommand = null; typedCommand = analyseGCodeCommand(tokens, intialContext); typedCommand.updateContext(intialContext); return typedCommand; } /** * Create a specialized GCodeCommand by calling the several builders * @param tokens the list of token * @param intialContext the initial context * @return a {@link GCodeCommand} * @throws GkException GkException */ private GCodeCommand analyseGCodeCommand(List<GCodeToken> tokens, GCodeContext context) throws GkException{ for (IRS274CommandBuilder<?> builder : lstBuilders) { if(builder.match(tokens, context)){ return builder.createCommand(tokens, context); } } String tokensString = ""; for (GCodeToken gCodeToken : tokens) { tokensString += gCodeToken.getValue(); } throw new GkTechnicalException("No builder found for command token list "+tokensString); } /** * Verify the modality of the token in a single line. If the modality constraint is violated, an exception is thrown. * @param tokens the list of token * @throws GkException GkException */ public void verifyModality(List<GCodeToken> lstToken) throws GkException{ for (ModalGroup group : modalGroups) { group.verifyTokenModality(lstToken); } } }