/* * ****************************************************************************** * * Copyright (C) 2002-2015 by Pentaho : http://www.pentaho.com * * ****************************************************************************** * * 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 org.pentaho.di.trans.steps.getxmldata; import org.pentaho.di.core.Const; import org.pentaho.di.core.exception.KettleValueException; import org.pentaho.di.core.row.RowMetaInterface; import org.pentaho.di.core.row.ValueMetaInterface; import org.pentaho.di.trans.TransMeta; import org.pentaho.di.trans.step.BaseStepMeta; import org.pentaho.di.trans.step.StepMeta; import org.pentaho.dictionary.DictionaryConst; import org.pentaho.metaverse.api.IAnalysisContext; import org.pentaho.metaverse.api.IMetaverseNode; import org.pentaho.metaverse.api.IMetaverseObjectFactory; import org.pentaho.metaverse.api.MetaverseAnalyzerException; import org.pentaho.metaverse.api.MetaverseException; import org.pentaho.metaverse.api.StepField; import org.pentaho.metaverse.api.analyzer.kettle.ComponentDerivationRecord; import org.pentaho.metaverse.api.analyzer.kettle.step.ExternalResourceStepAnalyzer; import org.pentaho.metaverse.api.model.IExternalResourceInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * The GetXMLDataStepAnalyzer is responsible for providing nodes and links (i.e. relationships) between itself and * other metaverse entities */ public class GetXMLDataStepAnalyzer extends ExternalResourceStepAnalyzer<GetXMLDataMeta> { private Logger log = LoggerFactory.getLogger( GetXMLDataStepAnalyzer.class ); @Override protected Set<StepField> getUsedFields( GetXMLDataMeta meta ) { Set<StepField> usedFields = new HashSet<>(); if ( meta.isInFields() ) { Set<StepField> stepFields = createStepFields( meta.getXMLField(), getInputs() ); usedFields.addAll( stepFields ); } return usedFields; } @Override public Set<Class<? extends BaseStepMeta>> getSupportedSteps() { return new HashSet<Class<? extends BaseStepMeta>>() { { add( GetXMLDataMeta.class ); } }; } @Override protected IMetaverseNode createOutputFieldNode( IAnalysisContext context, ValueMetaInterface fieldMeta, String targetStepName, String nodeType ) { IMetaverseNode fieldNode = super.createOutputFieldNode( context, fieldMeta, targetStepName, nodeType ); GetXMLDataField[] fields = baseStepMeta.getInputFields(); for ( GetXMLDataField field : fields ) { if ( fieldMeta.getName().equals( field.getName() ) ) { fieldNode.setProperty( "xpath", Const.NVL( field.getXPath(), "" ) ); fieldNode.setProperty( "element", Const.NVL( field.getElementTypeCode(), "" ) ); fieldNode.setProperty( "resultType", Const.NVL( field.getResultTypeCode(), "" ) ); fieldNode.setProperty( "repeat", field.isRepeated() ); break; } } return fieldNode; } @Override protected Map<String, RowMetaInterface> getInputRowMetaInterfaces( GetXMLDataMeta meta ) { Map<String, RowMetaInterface> inputRows = getInputFields( meta ); if ( inputRows == null ) { inputRows = new HashMap<>(); } // Get some boolean flags from the meta for easier access boolean isInFields = meta.isInFields(); boolean isAFile = meta.getIsAFile(); boolean isAUrl = meta.isReadUrl(); // only add resource fields if we are NOT getting the xml or file from a field if ( !isInFields || isAFile || isAUrl ) { RowMetaInterface stepFields = getOutputFields( meta ); RowMetaInterface clone = stepFields.clone(); // if there are previous steps providing data, we should remove them from the set of "resource" fields for ( RowMetaInterface rowMetaInterface : inputRows.values() ) { for ( ValueMetaInterface valueMetaInterface : rowMetaInterface.getValueMetaList() ) { try { clone.removeValueMeta( valueMetaInterface.getName() ); } catch ( KettleValueException e ) { // could not find it in the output, skip it } } } inputRows.put( RESOURCE, clone ); } return inputRows; } @Override public Set<ComponentDerivationRecord> getChangeRecords( GetXMLDataMeta meta ) throws MetaverseAnalyzerException { Set<ComponentDerivationRecord> changes = new HashSet<>(); boolean isInFields = meta.isInFields(); boolean isAFile = meta.getIsAFile(); boolean isAUrl = meta.isReadUrl(); // if we are getting xml from a field, we need to add the "derives" links from the xml to the output fields if ( isInFields && !isAFile && !isAUrl ) { GetXMLDataField[] fields = baseStepMeta.getInputFields(); if ( getInputs() != null ) { Set<StepField> inputFields = getInputs().getFieldNames(); for ( StepField inputField : inputFields ) { if ( inputField.getFieldName().equals( meta.getXMLField() ) ) { // link this to all of the outputs that come from the xml for ( GetXMLDataField field : fields ) { ComponentDerivationRecord change = new ComponentDerivationRecord( meta.getXMLField(), field.getName() ); changes.add( change ); } break; } } } } return changes; } @Override protected void customAnalyze( GetXMLDataMeta meta, IMetaverseNode node ) throws MetaverseAnalyzerException { super.customAnalyze( meta, node ); // Add the XPath Loop to the step node node.setProperty( "loopXPath", meta.getLoopXPath() ); } @Override public IMetaverseNode createResourceNode( IExternalResourceInfo resource ) throws MetaverseException { return createFileNode( resource.getName(), descriptor ); } @Override public String getResourceInputNodeType() { return DictionaryConst.NODE_TYPE_FILE_FIELD; } @Override public String getResourceOutputNodeType() { return null; } @Override public boolean isOutput() { return false; } @Override public boolean isInput() { return true; } ///// used for unit testing protected void setObjectFactory( IMetaverseObjectFactory factory ) { this.metaverseObjectFactory = factory; } protected void setRootNode( IMetaverseNode node ) { rootNode = node; } protected void setBaseStepMeta( GetXMLDataMeta meta ) { baseStepMeta = meta; } protected void setParentTransMeta( TransMeta tm ) { parentTransMeta = tm; } protected void setParentStepMeta( StepMeta sm ) { parentStepMeta = sm; } ///// used for unit testing }