From e412ae7092decd0019d814f7a72a4bae1017da89 Mon Sep 17 00:00:00 2001 From: ebner Date: Wed, 16 Mar 2016 13:29:02 +0100 Subject: [PATCH] merged cdump code which this project --- build.gradle | 1 - src/main/java/ch/psi/fda/cdump/Cdump.java | 151 ++++++++++++++++++ .../ch/psi/fda/cdump/CdumpConfiguration.java | 87 ++++++++++ .../ch/psi/fda/cdump/CdumpEContainer.java | 73 +++++++++ .../psi/fda/cdump/CdumpEContainerFactory.java | 26 +++ .../ch/psi/fda/cdump/CdumpEDescriptor.java | 25 +++ .../fda/cdump/CdumpEDescriptorProvider.java | 44 +++++ .../java/ch/psi/fda/cdump/CdumpListener.java | 102 ++++++++++++ .../java/ch/psi/fda/cdump/ui/CdumpMain.java | 107 +++++++++++++ .../services/ch.psi.fda.DescriptorProvider | 1 + .../services/ch.psi.fda.EContainerFactory | 1 + .../ch/psi/fda/cdump/CdumpListenerTest.java | 45 ++++++ .../java/ch/psi/fda/cdump/CdumpTestIOC.java | 79 +++++++++ 13 files changed, 741 insertions(+), 1 deletion(-) create mode 100644 src/main/java/ch/psi/fda/cdump/Cdump.java create mode 100644 src/main/java/ch/psi/fda/cdump/CdumpConfiguration.java create mode 100644 src/main/java/ch/psi/fda/cdump/CdumpEContainer.java create mode 100644 src/main/java/ch/psi/fda/cdump/CdumpEContainerFactory.java create mode 100644 src/main/java/ch/psi/fda/cdump/CdumpEDescriptor.java create mode 100644 src/main/java/ch/psi/fda/cdump/CdumpEDescriptorProvider.java create mode 100644 src/main/java/ch/psi/fda/cdump/CdumpListener.java create mode 100644 src/main/java/ch/psi/fda/cdump/ui/CdumpMain.java create mode 100644 src/main/resources/META-INF/services/ch.psi.fda.DescriptorProvider create mode 100644 src/main/resources/META-INF/services/ch.psi.fda.EContainerFactory create mode 100644 src/test/java/ch/psi/fda/cdump/CdumpListenerTest.java create mode 100644 src/test/java/ch/psi/fda/cdump/CdumpTestIOC.java diff --git a/build.gradle b/build.gradle index f2da171..562073b 100644 --- a/build.gradle +++ b/build.gradle @@ -14,7 +14,6 @@ repositories { dependencies { compile 'ch.psi:ch.psi.fda.core:2.3.4' compile 'ch.psi.fda:ch.psi.fda.xscan:2.6.8' - compile 'ch.psi:ch.psi.fda.cdump:2.3.4' compile 'ch.psi:ch.psi.fda.fdaq:2.3.4' compile 'ch.psi:jcae:2.4.1' compile 'com.google.inject:guice:3.0' diff --git a/src/main/java/ch/psi/fda/cdump/Cdump.java b/src/main/java/ch/psi/fda/cdump/Cdump.java new file mode 100644 index 0000000..d664305 --- /dev/null +++ b/src/main/java/ch/psi/fda/cdump/Cdump.java @@ -0,0 +1,151 @@ +/** + * + * Copyright 2010 Paul Scherrer Institute. All rights reserved. + * + * This code is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This code 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 Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + * + */ + +package ch.psi.fda.cdump; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; +import java.util.logging.Logger; + +import com.google.common.eventbus.EventBus; + +import ch.psi.jcae.Channel; +import ch.psi.jcae.ChannelDescriptor; +import ch.psi.jcae.ChannelException; +import ch.psi.jcae.ChannelService; + +/** + * Cdump readout logic - i.e. put monitor on a data waveform channel of the fast + * ADC and send data to the eventbus + */ +public class Cdump { + + private static final Logger logger = Logger.getLogger(Cdump.class.getName()); + + public final static String[] SAMPLING_RATES = new String[] {"1Hz","2Hz", "5Hz", "10Hz", "20Hz", "50Hz", "100Hz", "200Hz", "500Hz", + "1kHz", "2kHz", "5kHz", "10kHz", "20kHz", "50kHz", "100kHz"}; + + private Channel adcData; + + private enum AdcCmd { + READY, GO + }; + + private Channel adcCmd; + + private CdumpListener listener; + private ChannelService cservice; + private CdumpConfiguration configuration; + + public Cdump(ChannelService cservice, EventBus ebus, CdumpConfiguration configuration) { + this.cservice = cservice; + this.configuration = configuration; + this.listener = new CdumpListener(ebus, configuration.getNelements()); + } + + /** + * Acquire data with the given sampling rate + * @param samplingRate + */ + public void acquire(String samplingRate) { + + logger.info("Start acquisition with sampling rate "+ samplingRate); + + try { + // Set ADC sampling rate + Channel smplRate = cservice.createChannel(new ChannelDescriptor<>(Integer.class, configuration.getSamplingRateChannel(), false)); + smplRate.setValue(getIntSamplingRate(samplingRate)); + smplRate.destroy(); + + adcData = cservice.createChannel(new ChannelDescriptor<>(int[].class, configuration.getDataChannel(), true)); + adcCmd = cservice.createChannel(new ChannelDescriptor<>(Integer.class, configuration.getControlChannel(), false)); + + adcCmd.setValue(AdcCmd.GO.ordinal()); + adcData.addPropertyChangeListener(listener); + } catch (ChannelException | TimeoutException | InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + } + + /** + * Wait until acquire is done + */ + public void waitAcquireDone(){ + try { + adcCmd.waitForValue(AdcCmd.READY.ordinal()); + } catch (InterruptedException | ExecutionException | ChannelException e) { + throw new RuntimeException(e); + } + } + + public void stop() { + + logger.info("Stop acquisition"); + + try { + // Detach listener from channel - i.e. stop data acquisition + adcData.removePropertyChangeListener(listener); + adcCmd.setValue(AdcCmd.READY.ordinal()); + + listener.terminate(); + + adcCmd.destroy(); + adcData.destroy(); + } catch (ChannelException | InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + } + + /** + * Get sampling rate int value based on the passed rate string. + * If the string does not match any of the strings specified in the rates variable + * this function will set the rate to 1Hz + * + * 0 = 1Hz + * 1 = 2Hz + * 2 = 5Hz + * 3 = 10Hz + * 4 = 20Hz + * 5 = 50Hz + * 6 = 100Hz + * 7 = 200Hz + * 8 = 500Hz + * 9 = 1000Hz + * 10 = 2000Hz + * 11 = 5000Hz + * 12 = 10000Hz + * 13 = 20000Hz + * 14 = 50000Hz + * 15 = 100000Hz + * + * @param rate + */ + private int getIntSamplingRate(String rate){ + + for(int i=0;i. + * + */ + +package ch.psi.fda.cdump; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.Properties; + + +public class CdumpConfiguration { + + public final static String CDUMP_CONFIG = "ch.psi.fda.cdump.config.file"; + + private String dataChannel; + private int nelements = 65536; + private String controlChannel; + private String samplingRateChannel; + + public CdumpConfiguration(){ + String config = System.getProperty(CDUMP_CONFIG); + + if(config != null){ + loadFile(new File(config)); + } + else{ + throw new RuntimeException("No configuration file specified via -D"+CDUMP_CONFIG+"=..."); + } + } + + public void loadFile(File file) { + Properties properties = new Properties(); + + if(file!=null){ + try { + properties.load(new FileReader(file)); + } catch (IOException e) { + throw new RuntimeException("Cannot read file "+file, e); + } + } + + dataChannel = properties.getProperty(CdumpConfiguration.class.getPackage().getName()+".dataChannel", ""); + controlChannel = properties.getProperty(CdumpConfiguration.class.getPackage().getName()+".controlChannel", ""); + samplingRateChannel = properties.getProperty(CdumpConfiguration.class.getPackage().getName()+".samplingRateChannel", ""); + nelements = Integer.parseInt(properties.getProperty(CdumpConfiguration.class.getPackage().getName()+".nelements", "65536")); + + } + + public String getDataChannel() { + return dataChannel; + } + public void setDataChannel(String dataChannel) { + this.dataChannel = dataChannel; + } + public String getControlChannel() { + return controlChannel; + } + public void setControlChannel(String controlChannel) { + this.controlChannel = controlChannel; + } + public String getSamplingRateChannel() { + return samplingRateChannel; + } + public void setSamplingRateChannel(String samplingRateChannel) { + this.samplingRateChannel = samplingRateChannel; + } + public int getNelements() { + return nelements; + } +} diff --git a/src/main/java/ch/psi/fda/cdump/CdumpEContainer.java b/src/main/java/ch/psi/fda/cdump/CdumpEContainer.java new file mode 100644 index 0000000..427e9d1 --- /dev/null +++ b/src/main/java/ch/psi/fda/cdump/CdumpEContainer.java @@ -0,0 +1,73 @@ +package ch.psi.fda.cdump; + +import java.io.File; + +import com.google.common.eventbus.EventBus; + +import ch.psi.fda.EContainer; +import ch.psi.fda.messages.EndOfStreamMessage; +import ch.psi.fda.serializer.SerializerTXT; +import ch.psi.jcae.ChannelService; + +public class CdumpEContainer implements EContainer { + + private final ChannelService cservice; + private final CdumpEDescriptor edescriptor; + private final EventBus eventbus; + + private Cdump cdump; + private SerializerTXT serializer; + + private volatile boolean running = false; + + public CdumpEContainer(ChannelService cservice, EventBus eventbus, CdumpEDescriptor edescriptor) { + this.cservice = cservice; + this.eventbus = eventbus; + this.edescriptor = edescriptor; + } + + @Override + public void initialize() { + cdump = new Cdump(cservice, eventbus, new CdumpConfiguration()); + + File file = new File(edescriptor.getFileName()); + file.getParentFile().mkdirs(); // Create data base directory + + serializer = new SerializerTXT(file); + serializer.setShowDimensionHeader(false); + + eventbus.register(serializer); + } + + @Override + public void execute() { + running = true; + try{ + cdump.acquire(edescriptor.getSamplingRate()); + cdump.waitAcquireDone(); + } + finally{ + running=false; + } + } + + @Override + public void abort() { + eventbus.post(new EndOfStreamMessage()); + cdump.stop(); + running = false; + + eventbus.unregister(serializer); + } + + @Override + public boolean isActive() { + return running; + } + + @Override + public void destroy() { + abort(); + } + +} diff --git a/src/main/java/ch/psi/fda/cdump/CdumpEContainerFactory.java b/src/main/java/ch/psi/fda/cdump/CdumpEContainerFactory.java new file mode 100644 index 0000000..ca3cc7f --- /dev/null +++ b/src/main/java/ch/psi/fda/cdump/CdumpEContainerFactory.java @@ -0,0 +1,26 @@ +package ch.psi.fda.cdump; + +import javax.inject.Inject; + +import com.google.common.eventbus.EventBus; + +import ch.psi.fda.EContainer; +import ch.psi.fda.EContainerFactory; +import ch.psi.fda.edescriptor.EDescriptor; +import ch.psi.jcae.ChannelService; + +public class CdumpEContainerFactory implements EContainerFactory { + + @Inject + private ChannelService cservice; + + @Override + public boolean supportsEDescriptor(EDescriptor descriptor) { + return descriptor instanceof CdumpEDescriptor; + } + + @Override + public EContainer getEContainer(EDescriptor descriptor, EventBus bus) { + return new CdumpEContainer(cservice, bus, (CdumpEDescriptor) descriptor); + } +} diff --git a/src/main/java/ch/psi/fda/cdump/CdumpEDescriptor.java b/src/main/java/ch/psi/fda/cdump/CdumpEDescriptor.java new file mode 100644 index 0000000..a937360 --- /dev/null +++ b/src/main/java/ch/psi/fda/cdump/CdumpEDescriptor.java @@ -0,0 +1,25 @@ +package ch.psi.fda.cdump; + +import javax.xml.bind.annotation.XmlRootElement; + +import ch.psi.fda.edescriptor.EDescriptor; + +@XmlRootElement(name="cdump") +public class CdumpEDescriptor implements EDescriptor { + + private String samplingRate; + private String fileName; + + public String getSamplingRate() { + return samplingRate; + } + public void setSamplingRate(String samplingRate) { + this.samplingRate = samplingRate; + } + public String getFileName() { + return fileName; + } + public void setFileName(String fileName) { + this.fileName = fileName; + } +} diff --git a/src/main/java/ch/psi/fda/cdump/CdumpEDescriptorProvider.java b/src/main/java/ch/psi/fda/cdump/CdumpEDescriptorProvider.java new file mode 100644 index 0000000..20c4a24 --- /dev/null +++ b/src/main/java/ch/psi/fda/cdump/CdumpEDescriptorProvider.java @@ -0,0 +1,44 @@ +package ch.psi.fda.cdump; + +import java.io.File; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; + +import ch.psi.fda.DescriptorProvider; +import ch.psi.fda.edescriptor.EDescriptor; +import ch.psi.fda.vdescriptor.VDescriptor; + +public class CdumpEDescriptorProvider implements DescriptorProvider { + + private EDescriptor edescriptor; + + @Override + public void load(File... files) { + try { + JAXBContext context = JAXBContext.newInstance(CdumpEDescriptor.class); + Unmarshaller u = context.createUnmarshaller(); + edescriptor = (EDescriptor) u.unmarshal(files[0]); + } catch (JAXBException e) { + throw new RuntimeException(e); + } + + } + + @Override + public EDescriptor getEDescriptor() { + return edescriptor; + } + + @Override + public VDescriptor getVDescriptor() { + return null; + } + + @Override + public Class getEDescriptorClass() { + return CdumpEDescriptor.class; + } + +} diff --git a/src/main/java/ch/psi/fda/cdump/CdumpListener.java b/src/main/java/ch/psi/fda/cdump/CdumpListener.java new file mode 100644 index 0000000..7863d4c --- /dev/null +++ b/src/main/java/ch/psi/fda/cdump/CdumpListener.java @@ -0,0 +1,102 @@ +/** + * + * Copyright 2013 Paul Scherrer Institute. All rights reserved. + * + * This code is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This code 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 Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + * + */ +package ch.psi.fda.cdump; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.List; + +import ch.psi.fda.messages.DataMessage; +import ch.psi.fda.messages.EndOfStreamMessage; +import ch.psi.fda.messages.Metadata; + +import com.google.common.eventbus.EventBus; + +/** + * Listener that monitors the adc data channel and splitting up the data + */ +public class CdumpListener implements PropertyChangeListener { + + private final EventBus bus; + private final int numberOfElements; + + private boolean first = true; + private int numberOfWaveforms = 0; + private final List metadata = new ArrayList<>(); + + public CdumpListener(EventBus bus, int numberOfElements){ + this.bus = bus; + this.numberOfElements = numberOfElements; + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if(evt.getPropertyName().equals("value")){ + transform((int[]) evt.getNewValue()); + } + } + + + /** + * Transform received waveform + * 1. Take channel waveform + * [wavefrom .......................................................] + * 2. Split up waveform + * [1-number of elements][2-number of elements][3-number of elements] + * 3. Rotate splitted waveforms + * [1-0,2-0,3-0] thats one message + * [1-1,2-1,3-1] + * ... + * [1-noe, 2-noe, 3-noe] + * + */ + public void transform(int[] value){ + + // The first time check whether received waveform is a multiple of the specified number of elements number + // Calculate how many waveforms are within the received waveform + if(first){ + first=false; + int nelements = value.length; + int n = nelements % numberOfElements; + if (n != 0) { + throw new RuntimeException("Array size is not a multiple of "+numberOfElements); + } + numberOfWaveforms = nelements / numberOfElements; + for(int i=0;i. + * + */ + +package ch.psi.fda.cdump.ui; + +import java.io.File; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; + +import com.google.common.eventbus.AsyncEventBus; +import com.google.common.eventbus.EventBus; + +import ch.psi.fda.cdump.Cdump; +import ch.psi.fda.cdump.CdumpConfiguration; +import ch.psi.fda.serializer.SerializerTXT; +import ch.psi.jcae.ChannelService; +import ch.psi.jcae.impl.DefaultChannelService; +import sun.misc.Signal; +import sun.misc.SignalHandler; + +@SuppressWarnings("restriction") +public class CdumpMain { + + public static void main(String[] args){ + + final ChannelService cservice = new DefaultChannelService(); + + if(args.length != 2){ + System.err.println("Usage: cdump "); + StringBuilder b = new StringBuilder(); + for(String s: Cdump.SAMPLING_RATES){ + b.append(s); + b.append(" "); + } + System.err.println("Supported rates: "+b.toString()); + System.exit(1); + } + + String samplingRate = args[0]; + + // Calculate data file location/name + String fname = args[1]; + + File f = new File(fname); + f.getParentFile().mkdirs(); // Create data base directory + + // Create execution service + EventBus eventbus = new AsyncEventBus(Executors.newSingleThreadExecutor()); + final Cdump service = new Cdump(cservice, eventbus, new CdumpConfiguration()); + + SerializerTXT serializer = new SerializerTXT(f); + serializer.setShowDimensionHeader(false); + + eventbus.register(serializer); + + // Stop/abort handling of acquisition + Signal.handle(new Signal("INT"), new SignalHandler() { + /** + * Thread save signal counter + */ + private AtomicInteger signalCount= new AtomicInteger(0); + + /** + * Testing signal handler (in Eclipse) use this after starting scan: + * + * SL5: A=`ps -ef | tail -10 | grep jav[a] | awk '{printf $2}'`;kill -2 $A + * MacOS X: A=`ps -ef | grep AcquisitionMai[n] | awk '{printf $2}'`;kill -2 $A + * + * on the command line use CTRL-C + */ + @Override + public void handle(Signal signal) { + + + int count = signalCount.incrementAndGet(); + + // If signal is received more than 1 time forcefully abort application + if(count>1){ + System.exit(2); + } + + service.stop(); + + cservice.destroy(); + } + }); + + service.acquire(samplingRate); + } + +} diff --git a/src/main/resources/META-INF/services/ch.psi.fda.DescriptorProvider b/src/main/resources/META-INF/services/ch.psi.fda.DescriptorProvider new file mode 100644 index 0000000..f31cdb5 --- /dev/null +++ b/src/main/resources/META-INF/services/ch.psi.fda.DescriptorProvider @@ -0,0 +1 @@ +ch.psi.fda.cdump.CdumpEDescriptorProvider diff --git a/src/main/resources/META-INF/services/ch.psi.fda.EContainerFactory b/src/main/resources/META-INF/services/ch.psi.fda.EContainerFactory new file mode 100644 index 0000000..88bc480 --- /dev/null +++ b/src/main/resources/META-INF/services/ch.psi.fda.EContainerFactory @@ -0,0 +1 @@ +ch.psi.fda.cdump.CdumpEContainerFactory \ No newline at end of file diff --git a/src/test/java/ch/psi/fda/cdump/CdumpListenerTest.java b/src/test/java/ch/psi/fda/cdump/CdumpListenerTest.java new file mode 100644 index 0000000..89af073 --- /dev/null +++ b/src/test/java/ch/psi/fda/cdump/CdumpListenerTest.java @@ -0,0 +1,45 @@ +/** + * + * Copyright 2013 Paul Scherrer Institute. All rights reserved. + * + * This code is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This code 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 Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + * + */ +package ch.psi.fda.cdump; + +import org.junit.Test; + +import ch.psi.fda.messages.Message; + +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; +public class CdumpListenerTest { + + @Test + public void test() { + EventBus bus = new EventBus(); + + bus.register(new Object(){ + @Subscribe + public void onMessage(Message m){ + System.out.println(m); + } + }); + + CdumpListener l = new CdumpListener(bus, 4); + l.transform(new int[] {1,2,3,4,11,12,13,14}); + l.transform(new int[] {5,6,7,8,15,16,17,18}); + } + +} diff --git a/src/test/java/ch/psi/fda/cdump/CdumpTestIOC.java b/src/test/java/ch/psi/fda/cdump/CdumpTestIOC.java new file mode 100644 index 0000000..41a8d55 --- /dev/null +++ b/src/test/java/ch/psi/fda/cdump/CdumpTestIOC.java @@ -0,0 +1,79 @@ +/** + * + * Copyright 2011 Paul Scherrer Institute. All rights reserved. + * + * This code is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * This code 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 Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + * + */ +package ch.psi.fda.cdump; + +import gov.aps.jca.cas.ProcessVariable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; +import java.util.logging.Logger; + +import ch.psi.jcae.cas.CaServer; +import ch.psi.jcae.cas.ProcessVariableInt; +import ch.psi.jcae.cas.ProcessVariableIntWaveform; + +public class CdumpTestIOC { + + private static final Logger logger = Logger.getLogger(CdumpTestIOC.class.getName()); + + public static void main(String[] args) { + + List processVariables = new ArrayList(); + + // Data channel + ProcessVariableIntWaveform pv = new ProcessVariableIntWaveform("CDUMP:WAVE", null, 8); + processVariables.add(pv); + + // This PV has the states READY (0) and GO (1) + ProcessVariableInt pvControl = new ProcessVariableInt("CDUMP:CONTROL", null); + processVariables.add(pvControl); + + // Sampling rate channel + //{"1Hz","2Hz", "5Hz", "10Hz", "20Hz", "50Hz", "100Hz", "200Hz", "500Hz", "1kHz", "2kHz", "5kHz", "10kHz", "20kHz", "50kHz", "100kHz"}; + ProcessVariableInt pvSamplingRate = new ProcessVariableInt("CDUMP:SAMPLING", null); + processVariables.add(pvSamplingRate); + + + CaServer s = new CaServer(processVariables); + s.startAsDaemon(); + + Deque deque = new LinkedList(); + deque.push(new int[] { 1, 2, 3, 4, 11, 12, 13, 14 }); + deque.push(new int[] { 5, 6, 7, 8, 15, 16, 17, 18 }); + + while (true) { + if (pvControl.getValue() == 1) { // if control channel is on GO + int[] v = deque.pollFirst(); + logger.finest(Arrays.toString(v)); + pv.setValue(v); + + deque.addLast(v); + } + + try { + Thread.sleep(100); + } catch (InterruptedException e) { + } + + } + } +}