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;
28  
29  import com.rapiddweller.benerator.BeneratorFactory;
30  import com.rapiddweller.benerator.consumer.FileExporter;
31  import com.rapiddweller.benerator.engine.parser.xml.BeneratorParseContext;
32  import com.rapiddweller.common.ExceptionUtil;
33  import com.rapiddweller.common.IOUtil;
34  import com.rapiddweller.common.RoundedNumberFormat;
35  import com.rapiddweller.common.converter.ConverterManager;
36  import com.rapiddweller.common.time.ElapsedTimeFormatter;
37  import com.rapiddweller.common.xml.XMLUtil;
38  import com.rapiddweller.profile.Profiler;
39  import com.rapiddweller.profile.Profiling;
40  import org.apache.logging.log4j.LogManager;
41  import org.apache.logging.log4j.Logger;
42  import org.w3c.dom.Document;
43  import org.w3c.dom.Element;
44  
45  import java.io.Closeable;
46  import java.io.IOException;
47  import java.util.ArrayList;
48  import java.util.List;
49  
50  /**
51   * Parses and executes a benerator descriptor file.<br/>
52   * <br/>
53   * Created at 26.02.2009 15:51:59
54   *
55   * @author Volker Bergmann
56   * @since 0.5.8
57   */
58  public class DescriptorRunner implements ResourceManager {
59  
60    /**
61     * The constant LOCALE_VM_PARAM.
62     */
63    public static final String LOCALE_VM_PARAM = "benerator.locale";
64  
65    private static final Logger LOGGER = LogManager.getLogger(DescriptorRunner.class);
66  
67    // attributes ------------------------------------------------------------------------------------------------------
68  
69    private final String uri;
70  
71    private final BeneratorContext context;
72  
73    /**
74     * The Factory.
75     */
76    final BeneratorFactory factory;
77    private List<String> generatedFiles;
78  
79    private final ResourceManagerSupportort.html#ResourceManagerSupport">ResourceManagerSupport resourceManager = new ResourceManagerSupport();
80    /**
81     * The Start time.
82     */
83    long startTime = 0;
84  
85  
86    // constructor -----------------------------------------------------------------------------------------------------
87  
88    /**
89     * Instantiates a new Descriptor runner.
90     *
91     * @param uri     the uri
92     * @param context the context
93     */
94    public DescriptorRunner(String uri, BeneratorContext context) {
95      this.uri = uri;
96      this.context = context;
97      this.factory = BeneratorFactory.getInstance();
98      this.generatedFiles = new ArrayList<>();
99      ConverterManager.getInstance().setContext(context);
100   }
101 
102   /**
103    * Reset monitor.
104    */
105   public static void resetMonitor() {
106     BeneratorMonitor.INSTANCE.reset();
107   }
108 
109   // interface -------------------------------------------------------------------------------------------------------
110 
111   /**
112    * Gets context.
113    *
114    * @return the context
115    */
116   public BeneratorContext getContext() {
117     return context;
118   }
119 
120   /**
121    * Run.
122    *
123    * @throws IOException the io exception
124    */
125   public void run() throws IOException {
126     Runtime runtime = Runtime.getRuntime();
127     BeneratorShutdownHookorShutdownHook.html#BeneratorShutdownHook">BeneratorShutdownHook hook = new BeneratorShutdownHook(this);
128     runtime.addShutdownHook(hook);
129     try {
130       runWithoutShutdownHook();
131     } finally {
132       runtime.removeShutdownHook(hook);
133     }
134   }
135 
136   /**
137    * Run without shutdown hook.
138    *
139    * @throws IOException the io exception
140    */
141   public void runWithoutShutdownHook() throws IOException {
142     execute(parseDescriptorFile());
143   }
144 
145   /**
146    * Parse descriptor file benerator root statement.
147    *
148    * @return the benerator root statement
149    * @throws IOException the io exception
150    */
151   public BeneratorRootStatement parseDescriptorFile() throws IOException {
152     Document document = XMLUtil.parse(uri);
153     Element root = document.getDocumentElement();
154     BeneratorParseContext parsingContext = factory.createParseContext(resourceManager);
155     BeneratorRootStatementiddweller/benerator/engine/BeneratorRootStatement.html#BeneratorRootStatement">BeneratorRootStatement statement = (BeneratorRootStatement) parsingContext.parseElement(root, null);
156     // prepare system
157     generatedFiles = new ArrayList<>();
158     context.setContextUri(IOUtil.getParentUri(uri));
159     return statement;
160   }
161 
162   /**
163    * Execute.
164    *
165    * @param rootStatement the root statement
166    */
167   public void execute(BeneratorRootStatement rootStatement) {
168     try {
169       startTime = System.currentTimeMillis();
170       // run AST
171       rootStatement.execute(context);
172       // calculate and print statistics
173       long elapsedTime = java.lang.System.currentTimeMillis() - startTime;
174       printStats(elapsedTime);
175       if (Profiling.isEnabled()) {
176         Profiler.defaultInstance().printSummary();
177       }
178       List<String> generations = getGeneratedFiles();
179       if (generations.size() > 0) {
180         LOGGER.info("Generated file(s): " + generations);
181       }
182     } catch (Throwable t) {
183       if (ExceptionUtil.containsException(OutOfMemoryError.class, t) && Profiling.isEnabled()) {
184         LOGGER.error("OutOfMemoryError! This probably happened because you activated profiling", t);
185       } else {
186         LOGGER.error("Error in Benerator execution", t);
187       }
188     } finally {
189       context.close();
190     }
191   }
192 
193   /**
194    * Gets generated files.
195    *
196    * @return the generated files
197    */
198   public List<String> getGeneratedFiles() {
199     return generatedFiles;
200   }
201 
202 
203   // ResourceManager interface implementation ------------------------------------------------------------------------
204 
205   @Override
206   public boolean addResource(Closeable resource) {
207     if (!resourceManager.addResource(resource)) {
208       return false;
209     } else if (resource instanceof FileExporter) {
210       generatedFiles.add(((FileExporter) resource).getUri());
211     }
212     return true;
213   }
214 
215   @Override
216   public void close() {
217     resourceManager.close();
218   }
219 
220 
221   // private helpers -------------------------------------------------------------------------------------------------
222 
223   private static void printStats(long elapsedTime) {
224     String message = "Created a total of " + BeneratorMonitor.INSTANCE.getTotalGenerationCount() + " entities";
225     if (elapsedTime != 0) {
226       long throughput = BeneratorMonitor.INSTANCE.getTotalGenerationCount() * 3600000L / elapsedTime;
227       message += " in " + ElapsedTimeFormatter.format(elapsedTime) + " (~" + RoundedNumberFormat.format(throughput, 0) + " p.h.)";
228     }
229     LOGGER.info(message);
230   }
231 
232 
233   // java.lang.Object overrides --------------------------------------------------------------------------------------
234 
235   @Override
236   public String toString() {
237     return getClass().getSimpleName();
238   }
239 
240 }