Commit 80cadf11 authored by Gino Tosti's avatar Gino Tosti
Browse files

implemented full CORBA support as in C++ MonCollector

parent c37941d1
Loading
Loading
Loading
Loading
+210 −0
Original line number Diff line number Diff line
package alma.TMCDB.MonitorCollectorImpl;

import java.util.logging.Logger;

import org.jacorb.orb.ORB;
import org.jacorb.poa.POA;
import org.omg.CORBA.InterfaceDef;
import org.omg.CORBA.InterfaceDefHelper;
import org.omg.CORBA.Object;
import org.omg.CORBA.SystemException;
import org.omg.PortableServer.Servant;

import alma.ACS.CBDescOut;
import alma.ACS.CBdoubleHelper;
import alma.ACS.CBdoubleOperations;
import alma.ACS.CBdoublePOA;
import alma.ACS.CBdoublePOATie;
import alma.ACS.OffShoot;
import alma.ACS.Property;
import alma.ACS.ROdouble;
import alma.ACS.ROdoubleHelper;
import alma.ACSErr.Completion;
import alma.JavaContainerError.wrappers.AcsJContainerServicesEx;
import alma.TMCDB.MonitorBlob;
import alma.TMCDB.doubleBlobData;
import alma.TMCDB.doubleBlobDataHelper;
import alma.TMCDB.doubleBlobDataSeqHelper;
import alma.acs.container.ContainerServices;

public class MPdouble extends MonitorPointHelper implements CBdoubleOperations {

	
	private doubleBlobData[] blobDataSeq_m =null;

	private CBdoublePOA server;
	
	private ROdouble property_m;
	
	

	public MPdouble(Logger log, String propertyName, long archivingInterval, Property propertyRef, MonitorBlob mb) {
		super(log, propertyName, archivingInterval,  propertyRef, mb);
		server =new CBdoublePOATie(this);
		monitorBlob_m=mb;
		monitorBlob_m.archiveOnChange = false;

		monitorBlob_m.typeOfValue  = alma.TMCDB.doubleValueType.value;
		monitorBlob_m.propertyName = propertyName;
		monitorBlob_m.blobDataSeq = ORB.init().create_any();
		//setMonitorServant(server);
		this.blobDataSeq_m =new doubleBlobData[prealocSeqLen_m];
		seqLen_m = prealocSeqLen_m;
		try
		{
			property_m=ROdoubleHelper.narrow(propertyRef);
			//m_logger.info("no such Characteristic for"+propertyName);
			if(property_m.default_timer_trigger()==0){
			
				m_logger.info("Default_timer_trigger=0 in Property:"+propertyName);
			}
		}
		catch(Exception ex)
		{
			m_logger.info("no such Characteristic for"+ex.getMessage());
		}
		
		m_logger.info("INIZIALIZZATA COMPONENTE "+propertyName);
	}

	@Override
	public void working(double value, Completion c, CBDescOut desc) {
		m_logger.info("---->Working on:"+propertyName_m);
	    // Still place in current available buffer segments
		m_logger.info("--->Received:"+value);
	    if ( curSeqPos_m < seqLen_m )
	    {
	        // This log is commented because of operational constraints that are currently using 'debug' as operation log setting
	        //ACS_SHORT_LOG((LM_DEBUG, "Adding data to buffer"));
	        // Add data to current position
	    	doubleBlobData a = new doubleBlobData();
			a.value = value;
			a.time = c.timeStamp;
			blobDataSeq_m[curSeqPos_m] = a;
			//blobDataSeq_m[curSeqPos_m].value = value;
			//blobDataSeq_m[curSeqPos_m].time = c.timeStamp;
	        // Increment current position pointer
	    	System.out.print("--->Received:"+value);
	        curSeqPos_m++;
	        // Increment initial position pointer if buffer is full
	        if (bufferFull)
	        {
	        	System.out.println("Data lost from buffer");
	            curSeqInit_m++;
	        }
	    }
	    else // Current available buffer segments are full
	    {
	        // Another segment can be created
	        if ( seqLen_m < (prealocSeqLen_m * maxSeqSegments_m ))
	        {
	        	m_logger.info("Creating new buffer segment and adding data to it");
	            // Create new segment
	            seqLen_m = seqLen_m + prealocSeqLen_m;
	            // blobDataSeq_m.length(seqLen_m);
	            // Add data to current position
	            doubleBlobData a = new doubleBlobData();
				a.value = value;
				a.time = c.timeStamp;
				blobDataSeq_m[curSeqPos_m] = a;
	            //blobDataSeq_m[curSeqPos_m].value = value;
		        //blobDataSeq_m[curSeqPos_m].time = c.timeStamp;
	            // Increment current position pointer
				m_logger.info("-->Received:"+value);
	            curSeqPos_m++;
	        }
	        else // No more segments allowed
	        {
	        	m_logger.warning("No more data segments are allowed. Buffer is full");
	            // Define buffer as full
	            bufferFull = true;
	            // Increment buffer initial position
	            curSeqInit_m++;
	            // Reset buffer current position
	            curSeqPos_m = 0;
	            // Add data to current position
	            //blobDataSeq_m[curSeqPos_m].value = value;
		        // blobDataSeq_m[curSeqPos_m].time = comp.timeStamp;
		        // Increment current position pointer
	            curSeqPos_m++;
	        }
	    }
		
	}

	@Override
	public void fillSeq() {
		
		//super.fillSeq();
		
		synchronized(mutex) {
		
		try {
			if (curSeqInit_m == 0)
		    {
		        //blobDataSeq_m =new doubleBlobData[curSeqPos_m];
				doubleBlobData[] tmpBlobDataSeq = new doubleBlobData[curSeqPos_m];
				for (int i = 0; i < curSeqPos_m; i++) {
					m_logger.info("1---> BlobDataSeq "+blobDataSeq_m[i].time+" "+blobDataSeq_m[i].value);
					tmpBlobDataSeq[i] = blobDataSeq_m[i];
				}
				doubleBlobDataSeqHelper.insert(monitorBlob_m.blobDataSeq, tmpBlobDataSeq);
		        //blobDataSeq_m = new doubleBlobData[seqLen_m];
		    }else {
		    	doubleBlobData[] tmpBlobDataSeq = new doubleBlobData[curSeqPos_m];
				for (int i = 0; i < curSeqPos_m; i++) {
					m_logger.info("2---> BlobDataSeq "+i+" "+blobDataSeq_m[i].time+" "+blobDataSeq_m[i].value);
					tmpBlobDataSeq[i] = blobDataSeq_m[(i+curSeqInit_m)%seqLen_m];
				}
				doubleBlobDataSeqHelper.insert(monitorBlob_m.blobDataSeq, tmpBlobDataSeq);
		    }
		}catch (Exception e) {
			m_logger.severe("execption:"+e.getMessage());
		}
		    		
		}
		
		curSeqPos_m = 0;
	    curSeqInit_m = 0;
	    bufferFull = false;
	    //System.out.println("---> fillSeq Stop, any type="+monitorBlob_m.blobDataSeq.type()+" (doubleBlobDataSeqHelper.type()=)"+doubleBlobDataSeqHelper.type());
	}

	@Override
	public void done(double value, Completion c, CBDescOut desc) {
		
		m_logger.info("Done!");
	}
	
	@Override
	public void activate(ContainerServices containerServices_m) {
		try
		{
			monitorServant_m = containerServices_m.activateOffShoot(server);
	                // At this point ref count of monitorServant_m will be 2
		}
		catch(SystemException ex)
		{
			ex.printStackTrace();
		} catch (AcsJContainerServicesEx e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	@Override
	public void deactivate(ContainerServices containerServices_m) {
		try
		{
			containerServices_m.deactivateOffShoot(server);
	                // At this point ref count of monitorServant_m will be 2
		}
		catch(SystemException | AcsJContainerServicesEx ex)
		{
			ex.printStackTrace();
		}
		
	}

}
+64 −37
Original line number Diff line number Diff line
@@ -5,13 +5,20 @@ package alma.TMCDB.MonitorCollectorImpl;

import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

import org.omg.CORBA.Any;
import org.omg.CORBA.InterfaceDef;
import org.omg.CORBA.InterfaceDefHelper;
import org.omg.CORBA.Object;

import alma.ACS.CBdouble;
import alma.ACS.CBdoubleHelper;
import alma.ACS.CBdoubleOperations;
import alma.ACS.CBdoublePOA;
import alma.ACS.CBdoublePOATie;
import alma.ACS.CBlongPOA;
import alma.ACS.CallbackHelper;
import alma.ACS.CharacteristicComponent;
import alma.ACS.CharacteristicComponentDesc;
import alma.ACS.NoSuchCharacteristic;
@@ -19,7 +26,10 @@ import alma.ACS.Property;
import alma.ACS.PropertyDesc;
import alma.TMCDB.MonitorBlob;
import alma.TMCDB.MonitorDataBlock;
import alma.TMCDB.doubleBlobData;
import alma.TMCDB.doubleBlobDataSeqHolder;
import alma.TMCDB.longBlobData;
import alma.TMCDB.longBlobDataSeqHolder;
import alma.acs.container.ContainerServices;
import alma.acs.time.TimeHelper;
import alma.acstime.Epoch;
@@ -34,23 +44,24 @@ public class MonitorComponent {
	ContainerServices containerServices_m;
	CharacteristicComponent component_m;
	CharacteristicComponentDesc compDesc_m;
	int numOfProp_m;
	int numOfProp_m=0;
	Logger m_logger;

	// Monitoring state
	boolean monitoring_m;
	boolean monitoring_m = false;

	/*
	 *  Time of monitoring start
	 *	TODO which Java type? is CORBA::ULongLong in acsCommonC.h
	 *  here is a long for compatibility with monitorDataBlock_m.startTime et similar
	 */
	Epoch m_monitoringStartTime;
	Epoch m_monitoringStartTime =null;

	/*
	 * List of monitored points, in C++ is a list with seqIndex_m as index. Here
	 * I'll use an HashMap with names as keys for the moment
	 */
	Map<String, MonitorPoint> monitorPoints_m;
	Map<String, MonitorPointHelper> monitorPoints_m =null;

	/*
	 * Index for each monitored points in monitorDataBlock_m.monitorBlobs[].
@@ -59,7 +70,7 @@ public class MonitorComponent {
	 */
	Map<String, Integer> monitorBlocksIndex_m = new HashMap<String, Integer>();

	MonitorDataBlock monitorDataBlock_m;
	MonitorDataBlock monitorDataBlock_m =null;

	/**
	 * @param comp
@@ -76,6 +87,7 @@ public class MonitorComponent {
		monitorDataBlock_m.componentName = comp.name();
		monitorDataBlock_m.startTime = 0;
		monitorDataBlock_m.stopTime = 0;
		m_logger=containerServices_m.getLogger();
	}

//	public void finalize() {
@@ -98,7 +110,7 @@ public class MonitorComponent {

		String prop = component_m.name()+":"+propertyName;

		System.out.println("---> MonitorComponent.enable_archiving "+prop);
		m_logger.info("---> MonitorComponent.enable_archiving "+prop);

		for (String propName : monitorPoints_m.keySet()) {
			if (monitorPoints_m.get(propName).getPropertyName().equals(prop))
@@ -108,10 +120,10 @@ public class MonitorComponent {

	public synchronized void addAllProperties() {

		System.out.println("---> MonitorComponent.addAllProperties");
		m_logger.info("---> MonitorComponent.addAllProperties");

		// TODO: what implementation of List/Collection for monitorPoints_m?
		monitorPoints_m = new HashMap<String, MonitorPoint>(numOfProp_m);
		monitorPoints_m = new HashMap<String, MonitorPointHelper>(numOfProp_m);
		monitorDataBlock_m.monitorBlobs = new MonitorBlob[numOfProp_m];

		for (PropertyDesc p : compDesc_m.properties) {
@@ -126,9 +138,8 @@ public class MonitorComponent {
			Object idef = p.property_ref._get_interface_def();
			InterfaceDef type = InterfaceDefHelper.narrow(idef);

			System.out.println("---> MonitorComponent.addAllProperties " + p.name + " " + type.name()
			m_logger.info("---> MonitorComponent.addAllProperties " + p.name + " " + type.name()
					+ " ");
			System.out.flush();

			/*
			 * TODO in C++ ACS::TimeInterval, is
@@ -211,10 +222,7 @@ public class MonitorComponent {

	private void addProperty(String propertyName, String propertyType,
			alma.ACS.Property propertyRef, long archivingInterval) {



		MonitorPoint mp;
		//MonitorPoint mp;

		// Adding the index property on monitorBlocksIndex_m
		int index = monitorBlocksIndex_m.size();
@@ -229,15 +237,21 @@ public class MonitorComponent {
		 */
		if (propertyType.endsWith("double")) {

			System.out.println("--->      double                  "+propertyName+", "+propertyType+", "+propertyRef+", "+archivingInterval);
			m_logger.info("--->      double                  "+propertyName+", "+propertyType+", "+propertyRef+", "+archivingInterval);

			if (propertyType.startsWith("RO")) {

				monitorDataBlock_m.monitorBlobs[index] = new MonitorBlob();
				mp = new MonitorPoint<CBdoublePOA, doubleBlobDataSeqHolder>(propertyName, propertyRef, propertyType, alma.TMCDB.doubleValueType.value, archivingInterval, monitorDataBlock_m.monitorBlobs[index]);

				monitorPoints_m.put(propertyName, mp);
				System.out.println("---> MonitorComponent added Property "+propertyName);
				//doubleBlobData[] list = new doubleBlobData[100];
				//MonitorPoint<CBdoublePOA, doubleBlobData> mp = new MonitorPoint<CBdoublePOA, doubleBlobData>(propertyName, propertyRef, propertyType, alma.TMCDB.doubleValueType.value, archivingInterval, monitorDataBlock_m.monitorBlobs[index]);
				MPdouble mp1 = new MPdouble(m_logger,propertyName,archivingInterval,propertyRef,monitorDataBlock_m.monitorBlobs[index]);
				//org.omg.CORBA.Object ob= CallbackHelper.narrow(mp);
				//CBdoublePOA ser =new CBdoublePOATie(mp1);
				//mp1.setMonitorServant(ser);
				//mp.setLogger(m_logger);
				mp1.activate(containerServices_m);
				monitorPoints_m.put(propertyName, mp1);
				m_logger.info("---> MonitorComponent added Property "+propertyName);

			}
//				else {
@@ -245,30 +259,43 @@ public class MonitorComponent {
//				mp = new Monitorable(TPROP, propertyName, archivingInterval, property, typeOfData, mb);
//			}

		}else if (propertyType.endsWith("long")) {

			m_logger.info("--->      double                  "+propertyName+", "+propertyType+", "+propertyRef+", "+archivingInterval);

			System.out.println("---> monitorPoints_m:");
			for (String m : monitorPoints_m.keySet()) {
				System.out.println("---> "+m);
			if (propertyType.startsWith("RO")) {

				monitorDataBlock_m.monitorBlobs[index] = new MonitorBlob();
				MonitorPoint<CBlongPOA, longBlobData> mp = new MonitorPoint<CBlongPOA, longBlobData>(propertyName, propertyRef, propertyType, alma.TMCDB.longValueType.value, archivingInterval, monitorDataBlock_m.monitorBlobs[index]);

				//monitorPoints_m.put(propertyName, mp);
				m_logger.info("---> MonitorComponent added Property "+propertyName);
			}
		}else {
			m_logger.info("UNIMPLEMENTED Porperty Type:"+propertyType);
		}
		
		m_logger.info("---> the following monitorPoint has been added");
		for (String m : monitorPoints_m.keySet()) {
			m_logger.info("---> "+m);
		}
		
	}

	public void startMonitoring() {

		System.out.println("---> MonitorComponent.startMonitoring");
		System.out.println("---> # monitor points: "+monitorPoints_m.size());
		m_logger.info("---> MonitorComponent.startMonitoring");
		m_logger.info("---> # monitor points: "+monitorPoints_m.size());
		for (String propName : monitorPoints_m.keySet()) {
			System.out.println("----> "+propName);
			System.out.println("----> "+monitorPoints_m.get(propName).toString());
			m_logger.info("----> "+propName);
			m_logger.info("----> "+monitorPoints_m.get(propName).toString());
		}


		for (String propName : monitorPoints_m.keySet()) {
//			monitorPoints_m.get(propName).startMonitoring(containerServices_m);

			monitorPoints_m.get(propName).startMonitoring(containerServices_m);
		}

		// set monitoring state
		monitoring_m = true;

@@ -282,7 +309,7 @@ public class MonitorComponent {

	public void stopMonitoring() {

		System.out.println("---> MonitorComponent.stopMonitoring");
		m_logger.info("---> MonitorComponent.stopMonitoring");
		if (monitoring_m) {
			for (String propName : monitorPoints_m.keySet()) {
				monitorPoints_m.get(propName).stopMonitoring();
@@ -307,7 +334,7 @@ public class MonitorComponent {

		String prop = component_m.name()+":"+propertyName;

		System.out.println("---> MonitorComponent.set_archiving_interval "+prop);
		m_logger.info("---> MonitorComponent.set_archiving_interval "+prop);

		for (String propName : monitorPoints_m.keySet()) {
			if (monitorPoints_m.get(propName).getPropertyName().equals(prop))
@@ -319,7 +346,7 @@ public class MonitorComponent {

		String prop = component_m.name()+":"+propertyName;

		System.out.println("---> MonitorComponent.suppress_archiving "+prop);
		m_logger.info("---> MonitorComponent.suppress_archiving "+prop);

		for (String propName : monitorPoints_m.keySet()) {
			if (monitorPoints_m.get(propName).getPropertyName().equals(prop))
@@ -330,7 +357,7 @@ public class MonitorComponent {

	public synchronized void setDeviceSerialNumber(String serialNumber) {

		System.out.println("---> MonitorComponent.setDeviceSerialNumber");
		m_logger.info("---> MonitorComponent.setDeviceSerialNumber");

		monitorDataBlock_m.deviceSerialNumber = serialNumber;
	}
@@ -338,7 +365,7 @@ public class MonitorComponent {
	public synchronized void setPropertySerialNumber(String propertyName,
			String[] serialNumbers) {

		System.out.println("---> MonitorComponent.setPropertySerialNumber");
		m_logger.info("---> MonitorComponent.setPropertySerialNumber");

		for (String propName : monitorPoints_m.keySet()) {

@@ -353,7 +380,7 @@ public class MonitorComponent {

	public synchronized void fillSeq() {

		System.out.println("---> MonitorComponent.fillSeq");
		m_logger.info("---> MonitorComponent.fillSeq");

		if (monitoring_m) {
			// TODO: really it could be undefined here?
+18 −6
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ package alma.TMCDB.MonitorCollectorImpl;

import java.io.Serializable;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jacorb.orb.Any;
import org.jacorb.orb.ORB;
@@ -23,22 +24,25 @@ import alma.ACS.ROdouble;
import alma.ACS.ROdoubleHelper;
import alma.ACS.Subscription;
import alma.ACS.CBdoublePOA;
import alma.ACS.CallbackOperations;
import alma.ACS.CBBoolPOA;
import alma.ACS.CBDescIn;
import alma.ACSErr.Completion;
import alma.ACSErr.CompletionHolder;
import alma.JavaContainerError.wrappers.AcsJContainerServicesEx;
import alma.TMCDB.MonitorBlob;
import alma.TMCDB.doubleBlobData;
import alma.TMCDB.doubleBlobDataHolder;
import alma.TMCDB.doubleBlobDataSeqHelper;
import alma.acs.container.ContainerServices;
import alma.acs.time.TimeHelper;
import alma.TMCDB.MonitorCollectorImpl.Monitorable;


/**
 * @author Claudio Tanci
 *
 */
public class MonitorPoint<T extends Servant & OffShootOperations, TBLOB_SEQ extends org.omg.CORBA.portable.Streamable> implements Monitorable {
public class MonitorPoint<T extends Servant & OffShootOperations, TBLOB_SEQ extends org.omg.CORBA.portable.IDLEntity> implements Monitorable {

	private Monitor monitor;			// monitor of the property
	private Boolean monitorSuppressed;
@@ -51,14 +55,13 @@ public class MonitorPoint<T extends Servant & OffShootOperations, TBLOB_SEQ exte
	private long archivingInterval;		// interval in which the value should be archived (and so monitored)
	private MonitorBlob monitorBlob;

//	private TBLOB_SEQ[] blobDataSeq;
	private TBLOB_SEQ blobDataSeq1; 
	private doubleBlobData[] blobDataSeq = new doubleBlobData[100];

	private int curSeqPos = 0;

	// TODO review
	private OffShootOperations monitorCallback; // in C++ there is a ACS::OffShoot_var monitorCallback_m and a ACS::OffShoot_var alarmCallback_m
	private T monitorServant_m;
	private Logger m_logger;

	public MonitorPoint(String propertyName, Property propertyRef,
			String propertyType, short propertyValueType, long archivingInterval, MonitorBlob monitorBlob) {
@@ -130,6 +133,7 @@ public class MonitorPoint<T extends Servant & OffShootOperations, TBLOB_SEQ exte

			System.out.println("----> "+name+" "+type);
			if (type.equals("ROdouble")) {
				//CBdoublePOA m_cb = new CBdoublePOA()
				CBdoublePOA m_cb = new CBdoublePOA() {
					@Override
					public boolean negotiate(long time_to_transmit, CBDescOut desc) {
@@ -271,6 +275,7 @@ public class MonitorPoint<T extends Servant & OffShootOperations, TBLOB_SEQ exte

		System.out.println("---> fillSeq Start");
		

		doubleBlobData[] tmpBlobDataSeq = new doubleBlobData[curSeqPos];
		for (int i = 0; i < curSeqPos; i++) {

@@ -280,7 +285,6 @@ public class MonitorPoint<T extends Servant & OffShootOperations, TBLOB_SEQ exte

//		monitorBlob.blobDataSeq = ORB.init().create_any();
		doubleBlobDataSeqHelper.insert(monitorBlob.blobDataSeq, tmpBlobDataSeq);

		//set a length of a sequence back
		curSeqPos = 0;

@@ -292,4 +296,12 @@ public class MonitorPoint<T extends Servant & OffShootOperations, TBLOB_SEQ exte
		return name;
	}

	@Override
	public void setLogger(Logger log) {
		m_logger=log;
		
	}



}
+72 −0
Original line number Diff line number Diff line
package alma.TMCDB.MonitorCollectorImpl;

import java.util.logging.Logger;

import org.omg.PortableServer.Servant;

import alma.ACS.Monitor;
import alma.ACS.OffShoot;
import alma.ACS.Property;
import alma.TMCDB.MonitorBlob;
import alma.acs.container.ContainerServices;

public abstract class MonitorPointBase {
	
	protected String propertyName_m; /// property name

	protected long archivingInterval_m; // interval in which the value should be archived (and so monitored)

	protected double valuePercentTrigger_m=0; // Delta value percentage a value can change before the value should be archived (and so monitored)

	protected MonitorBlob monitorBlob_m =null; ///here we put the values
	
	protected Property property_m;

	protected Monitor monitor_m = null; /// monitor of the property

	//Subscription_var subscription_m; /// Subscription for the alarm of the property

	OffShoot monitorCallback_m; ///callback CORBA reference
	//OffShoot alarmCallback_m; ///callback CORBA reference

	protected int curSeqPos_m = 0; ///current position to write in the sequence
	protected int curSeqInit_m = 0; ///current init of the circular buffer
	protected boolean bufferFull=false; ///status of buffer. If false data is sorted normally. If true buffer is full (data is stored but old data lost)

	protected int seqLen_m; ///sequence length

	protected boolean monitorSuppressed_m =false;
	//protected boolean alarmSuppressed_m=false ;
	//double alarmTimerTrigger_m;

	protected final int maxSeqSegments_m = 2; // maximum sequence segments. maxSeqSegments_m*prealocSeqLen_m defines the buffer maximum size
	protected final int prealocSeqLen_m = 100; // preallocated length of the sequence. This is the step that the sequence will grow

	protected Long backLogSize_m =32L;
	
	
	//org.omg.CORBA.Any[] blobDataSeqTemp_m;
	protected double valueTrigger_m=0.; // Delta value describing how much a value can change before the value should be archived (and so monitored)
	protected Logger m_logger;
	
	protected Object mutex =new Object();
	
	
	abstract void activate(ContainerServices containerServices_m);

	abstract void deactivate(ContainerServices containerServices_m);

	abstract void startMonitoring(ContainerServices containerServices_m);
	
	abstract void stopMonitoring();

	abstract void enable_archiving();

	abstract void suppress_archiving();

	abstract void set_archiving_interval(long time);

	abstract void setPropertySerialNumber(String[] serialNumbers);

	abstract String getPropertyName();
}
+259 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading