View Javadoc
1   /*
2    * (c) Copyright 2006-2020 by rapiddweller GmbH & Volker Bergmann. All rights reserved.
3    *
4    * Redistribution and use in source and binary forms, with or without
5    * modification, is permitted under the terms of the
6    * GNU General Public License.
7    *
8    * For redistributing this software or a derivative work under a license other
9    * than the GPL-compatible Free Software License as defined by the Free
10   * Software Foundation or approved by OSI, you must first obtain a commercial
11   * license to this software product from rapiddweller GmbH & Volker Bergmann.
12   *
13   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14   * WITHOUT A WARRANTY OF ANY KIND. ALL EXPRESS OR IMPLIED CONDITIONS,
15   * REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF
16   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE
17   * HEREBY EXCLUDED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24   * POSSIBILITY OF SUCH DAMAGE.
25   */
26  
27  package com.rapiddweller.benerator.engine.expression.xml;
28  
29  import com.rapiddweller.benerator.BeneratorFactory;
30  import com.rapiddweller.benerator.Consumer;
31  import com.rapiddweller.benerator.StorageSystem;
32  import com.rapiddweller.benerator.consumer.ConsumerChain;
33  import com.rapiddweller.benerator.consumer.NonClosingConsumerProxy;
34  import com.rapiddweller.benerator.engine.BeneratorContext;
35  import com.rapiddweller.benerator.engine.ResourceManager;
36  import com.rapiddweller.benerator.engine.parser.xml.BeanParser;
37  import com.rapiddweller.benerator.storage.StorageSystemInserter;
38  import com.rapiddweller.common.BeanUtil;
39  import com.rapiddweller.common.Context;
40  import com.rapiddweller.common.Escalator;
41  import com.rapiddweller.common.LoggerEscalator;
42  import com.rapiddweller.common.xml.XMLUtil;
43  import com.rapiddweller.script.BeanSpec;
44  import com.rapiddweller.script.DatabeneScriptParser;
45  import com.rapiddweller.script.expression.DynamicExpression;
46  import org.w3c.dom.Element;
47  
48  import static com.rapiddweller.benerator.engine.DescriptorConstants.ATT_CLASS;
49  import static com.rapiddweller.benerator.engine.DescriptorConstants.ATT_CONSUMER;
50  import static com.rapiddweller.benerator.engine.DescriptorConstants.ATT_NAME;
51  import static com.rapiddweller.benerator.engine.DescriptorConstants.ATT_REF;
52  import static com.rapiddweller.benerator.engine.DescriptorConstants.ATT_SPEC;
53  import static com.rapiddweller.benerator.engine.DescriptorConstants.EL_CONSUMER;
54  import static com.rapiddweller.benerator.parser.xml.XmlDescriptorParser.parseStringAttribute;
55  
56  /**
57   * Parses a {@link Consumer} specification in an XML element in a descriptor file.<br/><br/>
58   * Created at 24.07.2009 07:21:16
59   *
60   * @author Volker Bergmann
61   * @since 0.6.0
62   */
63  public class XMLConsumerExpression extends DynamicExpression<Consumer> {
64  
65    private final Escalator escalator;
66  
67    private final Element entityElement;
68    private final boolean consumersExpected;
69    private final ResourceManager resourceManager;
70  
71    /**
72     * Instantiates a new Xml consumer expression.
73     *
74     * @param entityElement     the entity element
75     * @param consumersExpected the consumers expected
76     * @param resourceManager   the resource manager
77     */
78    public XMLConsumerExpression(Element entityElement, boolean consumersExpected, ResourceManager resourceManager) {
79      this.entityElement = entityElement;
80      this.consumersExpected = consumersExpected;
81      this.escalator = new LoggerEscalator();
82      this.resourceManager = resourceManager;
83    }
84  
85    @Override
86    public Consumer evaluate(Context context) {
87      BeneratorContextm/rapiddweller/benerator/engine/BeneratorContext.html#BeneratorContext">BeneratorContext beneratorContext = (BeneratorContext) context;
88      ConsumerChainConsumerChain.html#ConsumerChain">ConsumerChain consumerChain = new ConsumerChain();
89  
90      // parse consumer attribute
91      if (entityElement.hasAttribute(ATT_CONSUMER)) {
92        String consumerSpec = parseStringAttribute(entityElement, ATT_CONSUMER, context);
93        BeanSpec[] beanSpecs = DatabeneScriptParser.resolveBeanSpecList(consumerSpec, beneratorContext);
94        for (BeanSpec beanSpec : beanSpecs) {
95          addConsumer(beanSpec, beneratorContext, consumerChain);
96        }
97      }
98  
99      // parse consumer sub elements
100     Element[] consumerElements = XMLUtil.getChildElements(entityElement, true, EL_CONSUMER);
101     for (Element consumerElement : consumerElements) {
102       BeanSpec beanSpec;
103       if (consumerElement.hasAttribute(ATT_REF)) {
104         String ref = parseStringAttribute(consumerElement, ATT_REF, context);
105         beanSpec = BeanSpec.createReference(beneratorContext.get(ref));
106       } else if (consumerElement.hasAttribute(ATT_CLASS) || consumerElement.hasAttribute(ATT_SPEC)) {
107         beanSpec = BeanParser.resolveBeanExpression(consumerElement, beneratorContext);
108       } else {
109         throw new UnsupportedOperationException(
110             "Can't handle " + XMLUtil.formatShort(consumerElement));
111       }
112       addConsumer(beanSpec, beneratorContext, consumerChain);
113     }
114 
115     if (consumerChain.componentCount() == 0 && consumersExpected) {
116       String entityName = parseStringAttribute(entityElement, ATT_NAME, context, false);
117       escalator.escalate("No consumers defined for " + entityName, this, null);
118     }
119     for (Consumer consumer : consumerChain.getComponents()) {
120       resourceManager.addResource(consumer);
121     }
122     return (consumerChain.componentCount() == 1 ? consumerChain.getComponent(0) : consumerChain);
123   }
124 
125   /**
126    * Add consumer.
127    *
128    * @param beanSpec the bean spec
129    * @param context  the context
130    * @param chain    the chain
131    */
132   public static void addConsumer(BeanSpec beanSpec, BeneratorContext context, ConsumerChain chain) {
133     Consumer consumer;
134     Object bean = beanSpec.getBean();
135     // check consumer type
136     if (bean instanceof Consumer) {
137       consumer = (Consumer) bean;
138     } else if (bean instanceof StorageSystem) {
139       consumer = new StorageSystemInserter((StorageSystem) bean);
140     } else {
141       throw new UnsupportedOperationException("Consumer type not supported: " + BeanUtil.simpleClassName(bean));
142     }
143     consumer = BeneratorFactory.getInstance().configureConsumer(consumer, context);
144     if (beanSpec.isReference()) {
145       consumer = new NonClosingConsumerProxy(consumer);
146     }
147     chain.addComponent(consumer);
148   }
149 
150   @Override
151   public String toString() {
152     return getClass().getSimpleName() + '(' + XMLUtil.formatShort(entityElement) + ')';
153   }
154 
155 }