function obj = loadobj(B)
%LOADOBJ Load filter for serial port objects.
%
%    OBJ = LOADOBJ(B) is called by LOAD when a serial port object is 
%    loaded from a .MAT file. The return value, OBJ, is subsequently 
%    used by LOAD to populate the workspace.  
%
%    LOADOBJ will be separately invoked for each object in the .MAT file.
%

%    MP 3-14-00
%    Copyright 2000 The MathWorks, Inc. 
%    $Revision: 1.5 $  $Date: 2000/08/29 23:48:20 $

% Warn if java is not running.
if ~usejava('jvm')
    % Store the warn state.
    warnstate = warning;
    
    % Warn nicely.
    if ~strcmp(warnstate, 'off')
        warning('on');
    end
    warning('The instrument object requires JAVA and was not loaded.');
    
    % Restore the warn state.
    warning(warnstate);
    
    % Return empty array.
    obj = [];
    return;
end

obj = B;

% Store the warning state.
warnState = warning;
needToWarn = 0;

% Change warning to on.
if ~strcmp(warnState, 'off');
    warning('on');
end    

% Find the instrument package.
instrPackage = findpackage('instrument');
if isempty(instrPackage)
	instrPackage = schema.package('instrument');
end

% Get the object's instrument object's store field.
instrumentField = igetfield(obj, 'instrument');
propInfo = igetfield(instrumentField, 'store');
if isempty(propInfo)
    return;
end

% Recreate the objects.
for i = 1:length(propInfo)
	% Get the property structure.
	propVals = propInfo(i).props;

    if isstr(propVals)
        propInfo(i).obj = handle(javaObject(propVals));
        dispose(propInfo(i).obj);
	elseif isstruct(propVals)
		% Create the object based on the type.
        constructorArgs = propVals.ConstructorArgs;
        if isjava(constructorArgs)
	        constructorArgs = cell(constructorArgs);
        end
		switch (propVals.Type)
    	case 'serial'
            port = propVals.Port;
			propInfo(i).obj = handle(com.mathworks.toolbox.instrument.SerialComm(port));
        case 'gpib'
            name = localFindGPIBName(constructorArgs{1});
            propInfo(i).obj = handle(javaObject(['com.mathworks.toolbox.instrument.Gpib' upper(name)], constructorArgs{:}));
        case 'visa-serial'
            propInfo(i).obj = handle(com.mathworks.toolbox.instrument.SerialVisa(constructorArgs{:}));
        case 'visa-gpib'
            propInfo(i).obj = handle(com.mathworks.toolbox.instrument.GpibVisa(constructorArgs{:}));   
        case 'visa-vxi'
            propInfo(i).obj = handle(com.mathworks.toolbox.instrument.VxiVisa(constructorArgs{:}));   
        case 'visa-gpib-vxi'
             propInfo(i).obj = handle(com.mathworks.toolbox.instrument.VxiGpibVisa(constructorArgs{:}));   
		end

        % Add to UDD database.
		connect(propInfo(i).obj, instrPackage.DefaultDatabase, 'up');

        % Reset the properties.
        propVals = rmfield(propVals, {'Type', 'ConstructorArgs'});
		set(propInfo(i).obj, propVals);
	else
		propInfo(i).obj = propVals;
    end
end

% Parse through each object's Action and UserData properties to determine
% if the values contain an instrument object.
localRestoreUserDataAndActionProps(propInfo);

% Restore the jobject field to the correct objects.
jobject = igetfield(obj, 'jobject');
for i = 1:length(jobject);
    out(i) = propInfo(jobject{i}).obj;
end

obj = isetfield(obj, 'jobject', out);


% **************************************************************************
% Restore the UserData and action properties.
function localRestoreUserDataAndActionProps(propInfo)

for i = 1:length(propInfo)
    % Get the current location of the object.
    currentObj = propInfo(i).obj;
    allLocations = propInfo(i).location;
    
    % Loop through each location and restore the object.
    for j = 1:length(allLocations)
        loc = allLocations{j};
        setObject = propInfo(loc.ObjectIndex).obj;
        currentPropValue = get(setObject, loc.Property);

        if isnumeric(loc.Index)
            % Contains a direct instrument object. Ex. s.UserData = s;
            currentPropValue = localFillInArray(currentPropValue, localWrapIntoInstrument(currentObj), loc.Index);
        else
            % Instrument object is within a structure or a cell.
            if (length(loc.Index) > 2) & (isnumeric(loc.Index{end}) & strcmp(loc.Index{end-1}, '()'))
                currentPropValue = localFillInStructOrCellWithArray(currentPropValue, localWrapIntoInstrument(currentObj), loc.Index);
            else
            	currentPropValue = localFillInStructOrCell(currentPropValue, localWrapIntoInstrument(currentObj), loc.Index);
            end
        end
        
        % Update the propInfo structure.
        eval(['propInfo(' num2str(loc.ObjectIndex) ').obj.' loc.Property ' =  currentPropValue;'])
    end    
end

% ****************************************************************************
% Fill in the array according to the index value.
function currentPropValue = localFillInStructOrCell(currentPropValue, obj, index);

% Build up the string to access the UDD object.
stringToAccessUDD = '';
for i = 1:2:length(index)
    currentDelimiter = index{i};
    switch (currentDelimiter)
    case '()'
        stringToAccessUDD = [stringToAccessUDD '(' num2str(index{i+1}) ')'];
    case '{}'
        stringToAccessUDD = [stringToAccessUDD '{' num2str(index{i+1}) '}'];
    case '.'
        stringToAccessUDD = [stringToAccessUDD '.' index{i+1}];
    end
end

% Set the property to the object.
eval(['currentPropValue' stringToAccessUDD ' = obj;']);

% ****************************************************************************
% Fill in the array according to the index value.
function currentPropValue = localFillInStructOrCellWithArray(currentPropValue, obj, index);

% Build up the string to access the UDD object.
stringToAccessUDD = '';
for i = 1:2:length(index)-2  
    currentDelimiter = index{i};
    switch (currentDelimiter)
    case '()'
        stringToAccessUDD = [stringToAccessUDD '(' num2str(index{i+1}) ')'];
    case '{}'
        stringToAccessUDD = [stringToAccessUDD '{' num2str(index{i+1}) '}'];
    case '.'
        stringToAccessUDD = [stringToAccessUDD '.' index{i+1}];
    end
end

% Set the property to the object.
if ~isempty(currentPropValue)
	val = eval(['currentPropValue' stringToAccessUDD ';']);
	val = localFillInArray(val, obj, index{end});
else
    val = localFillInArray('', obj, index{end});
end

eval(['currentPropValue' stringToAccessUDD ' = val;']);

% ****************************************************************************
% Fill in the array according to the index value.
function currentPropValue = localFillInArray(currentPropValue, obj, index);

len = length(currentPropValue);
if len == 0
    len = 1;
end

if index <= len
    if len == 1
        currentPropValue = obj;
    end
    currentPropValue = localReplaceElement(currentPropValue, {index}, obj);
else
    % Need to fill in something - Use the object.
    for i = len:index-1
        currentPropValue = [currentPropValue obj];
    end
end

% ****************************************************************************
% Wrap UDD object into a OOPs object.
function obj = localWrapIntoInstrument(uddObj)

if ~ishandle(uddObj)
	obj = uddObj;
	return;
end

switch class(uddObj)
case 'javahandle.com.mathworks.toolbox.instrument.SerialComm'
    obj = serial(uddObj);
case 'javahandle.com.mathworks.toolbox.instrument.SerialVisa' 
    obj = visa(uddObj);
case 'javahandle.com.mathworks.toolbox.instrument.GpibVisa'
    obj = visa(uddObj);
case 'javahandle.com.mathworks.toolbox.instrument.VxiVisa'
    obj = visa(uddObj);
case 'javahandle.com.mathworks.toolbox.instrument.VxiGpibVisa'
    obj = visa(uddObj);
otherwise
    % GPIB object.
	obj = gpib(uddObj);    
end

% *********************************************************************
% Replace the specified element.
function [obj, errflag] = localReplaceElement(obj, index, Value)

% Initialize variables.
errflag = 0;

try
   % Get the current state of the object.
   jobject = igetfield(obj, 'jobject');
   type = igetfield(obj, 'type');
   constructor = igetfield(obj, 'constructor');
   
   if ~iscell(type)
      type = {type};
   end
   
   if ~iscell(constructor)
       constructor = {constructor};
   end
   
   % Replace the specified index with Value.
   if ~isempty(Value)
       if ((length([index{1}]) > 1) & (length(Value) > 1))
           % Ex. y(:) = x(2:-1:1); where y and x are 1-by-2 instrument arrays.
           jobject(index{1}) = igetfield(Value, 'jobject');
      	   type(index{1}) = igetfield(Value, 'type');
           constructor(index{1}) = igetfield(Value, 'constructor');
       else
           % Ex. y(1) = x(2);
           % Ex. y(:) = x;
      	   jobject(index{1}) = igetfield(Value, 'jobject');
      	   type(index{1}) = {igetfield(Value, 'type')};
           constructor(index{1}) = {igetfield(Value, 'constructor')};
       end
   else
      jobject(index{1}) = [];
      type(index{1}) = [];
      constructor(index{1}) = [];
   end
   
   % Assign the new state back to the original object.
   obj = isetfield(obj, 'jobject', jobject);
   obj = isetfield(obj, 'type', type);
   obj = isetfield(obj, 'constructor', constructor);
catch
   errflag = 1;
   return
end

% *********************************************************************
% Find the GPIB vendor.
function name = localFindGPIBName(pathToDll);

[path, name, ext] = fileparts(pathToDll);

if strcmp(name(1:2), 'mw')
    name = name(3:end-4);
end
 

