702 lines
22 KiB
C#

/*********************************************************************************************
* Copyright 2004 - Volian Enterprises, Inc. All rights reserved.
* Volian Enterprises - Proprietary Information - DO NOT COPY OR DISTRIBUTE
* ------------------------------------------------------------------------------
* $Workfile: Plant.cs $ $Revision: 10 $
* $Author: Jsj $ $Date: 10/20/06 9:34a $
*
* $History: Plant.cs $
*
* ***************** Version 10 *****************
* User: Jsj Date: 10/20/06 Time: 9:34a
* Updated in $/LibSource/VEObject
* long name fix
*
* ***************** Version 9 *****************
* User: Jsj Date: 9/26/06 Time: 9:38a
* Updated in $/LibSource/VEObject
* check for a siingle quote in directory name
*
* ***************** Version 8 *****************
* User: Kathy Date: 6/06/05 Time: 12:35p
* Updated in $/LibSource/VEObject
* Allow lock set even if system lock set
*
* ***************** Version 7 *****************
* User: Kathy Date: 4/12/05 Time: 1:01p
* Updated in $/LibSource/VEObject
*
* ***************** Version 6 *****************
* User: Kathy Date: 2/02/05 Time: 10:13a
* Updated in $/LibSource/VEObject
* B2005-006: fix missing proc sets under plant
*
* ***************** Version 5 *****************
* User: Kathy Date: 1/31/05 Time: 11:06a
* Updated in $/LibSource/VEObject
* Fix B2005-005 (connection & delete directory errors). also, fix icon
* usage & security for new
*
* ***************** Version 4 *****************
* User: Kathy Date: 1/24/05 Time: 2:45p
* Updated in $/LibSource/VEObject
* B2005-004 fixes
*
* ***************** Version 3 *****************
* User: Kathy Date: 1/14/05 Time: 10:38a
* Updated in $/LibSource/VEObject
* B2004-061: Fix security optoins
*
* ***************** Version 2 *****************
* User: Kathy Date: 1/10/05 Time: 12:58p
* Updated in $/LibSource/VEObject
* B2004-063 fix
*
* ***************** Version 1 *****************
* User: Kathy Date: 7/27/04 Time: 8:53a
* Created in $/LibSource/VEObject
*********************************************************************************************/
using System;
using System.Collections;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Xml;
using System.ComponentModel;
using Utils;
using VENetwork;
namespace VEObject
{
/// <summary>
/// This defines the VEO_Plant class which handles plant data. This contains
/// support for the vexxx layer.
/// </summary>
public class VEO_Plant : VEO_Base
{
public long accessFlags;
protected string tmpTitle;
protected string tmpLocation;
protected bool changeLocation;
protected bool changeTitle;
private string PrevDirectory;
public VEO_Plant(UserRunTime iusrRunTime, string ititle, string ipath)
{
// iconStates are the imagelist indexes for the tree view (imglist1)
// the states are Nolock, LockedByMe, LockedByOther, LockPending, Empty.
iconStates = new int[5] {3,21,5,22,4};
_Title = ititle;
_Location = ipath;
usrRunTime = iusrRunTime;
changeLocation=false;
changeTitle=false;
IsEmpty=false;
VEObjectType=(int)VEObjectTypesDefs.Plant;
isNew=false;
LoadLockInfo();
icon = iconStates[(int)Lock.LockStatus];
if (Lock.LockStatus != VENetwork.Status.LockedByOther)
{
if (ipath != null)
{
string[] dirs = new string[40];
dirs = Directory.GetDirectories(ipath);
if (dirs.Length == 0)
{
IsEmpty=true;
//only reset the icon to empty if there is no lock icon.
//if a lock, show the lock icon
if (Lock.LockStatus == VENetwork.Status.NoLock) icon = iconStates[(int)VEO_IconStates.Empty];
}
}
}
}
public override void LoadLockInfo()
{
Lock = new VELock(_Location, usrRunTime.myUserData, usrRunTime.InMultiUserMode?VENetwork.LockTypes.Plant:VENetwork.LockTypes.None);
}
// Properties used for modify of 'Properties' from File menu.
[Description("Location"),Category("Plant"),ReadOnly(true)]public string Location
{
get{return _Location;}
set{_Location=value;}
}
[Description("Title"),Category("Plant")]public string Title
{
get
{
if (!changeTitle)
return _Title;
else
return tmpTitle;
}
set
{
changeTitle=true;
tmpTitle=value;
}
}
// The open method checks for multi-user settings at the plant level. It
// also positions into the plant directory.
public override bool Open()
{
isOpen = true;
PrevDirectory = Directory.GetCurrentDirectory();
if(_Location!=null)Directory.SetCurrentDirectory(_Location);
if (Connection!=null)Connection.Enter(false);
return true;
}
// The close method resets, if necessary from any multi-user settings and
// positions back to the datapath directory (which is a level above the
// current level)
public override bool Close()
{
if (!isOpen)return false;
isOpen=false;
if (Connection!=null)Connection.Exit();
Directory.SetCurrentDirectory("..");
return true;
}
public override void Restore()
{
changeTitle=false;
}
public override bool Delete()
{
DialogResult result = MessageBox.Show("Are you sure you want to delete the entire plant directory " + this._Location,"Confirm Delete Again",MessageBoxButtons.YesNoCancel);
if (result == DialogResult.Yes)
{
// delete the entire directory
if (Directory.Exists(this._Location))
{
if(isOpen)Close();
try
{
Directory.Delete(this._Location,true);
}
catch (Exception e)
{
MessageBox.Show("Could not delete directory - manually delete " + this._Location + ". Cause: " + e.Message);
}
if (Directory.Exists(this._Location))
{
MessageBox.Show("Unable to delete the plant directory.");
return false;
}
return true;
}
}
return false;
}
private void CreateProcSet(string dirpath, XmlElement nm, string dirname, long flags)
{
// see if there is a title file in the directory and use
// it if there is, otherwise use menuname & if there's no menu
// name, use the directory name.
VEO_ProcSet procset = null;
string titlepath = dirpath + "\\" + "Title";
FileInfo fi = new FileInfo(titlepath);
if (File.Exists(titlepath))
{
StreamReader myReader = new StreamReader(titlepath);
titlepath = myReader.ReadLine();
myReader.Close();
procset = new VEO_ProcSet(usrRunTime, titlepath.Trim(), dirpath, flags);
}
else
{
if (nm != null)
procset = new VEO_ProcSet(usrRunTime, nm.InnerText, dirpath, flags);
else
{
string tmpdirnm = dirname;
int indx=0;
// if this is temp change directory, tack on text to recognize it
if ((indx=dirpath.ToUpper().IndexOf("TMPCHG"))>-1)
tmpdirnm = dirname + " - Temporary Change Version";
// if this is approved, tack on Current Approved Version to the title
else if ((indx=dirpath.ToUpper().IndexOf("APPROVED"))>-1)
tmpdirnm = dirname + " - Current Approved Version";
procset = new VEO_ProcSet(usrRunTime, tmpdirnm, dirpath,flags);
}
}
procset.parentObj = this;
Children.Add(procset);
}
// private method, used below, to add a directory to the child list
// (list contains proc sets)
private bool ProcessDirName(XmlElement par, string dirname, int plntsecindx)
{
XmlNodeList nodeList = par.SelectNodes("ProcFile");
if (nodeList == null) return false;
foreach (XmlNode dirnd in nodeList)
{
XmlElement dele=(XmlElement)dirnd;
string dirpath = _Location + "\\" + dirname;
if (File.Exists(dirpath+"\\"+dirnd.InnerText))
{
//
// see if there's an exception or a requirement, i.e. use
// the Working Draft if there's no proc2 directory (Except)
// or use the Working Draft Unit 1 if there's a proc2
// directory (Require)
bool excpt = false;
bool req = true;
string path1=null;
XmlElement except = (XmlElement) par.SelectSingleNode("Exception");
if (except != null)
{
// if this exception directory exists, don't add this to
// the set.
path1 = dirpath + "\\" + except.InnerText;
if (Directory.Exists(path1)) excpt = true;
}
XmlElement require = (XmlElement) par.SelectSingleNode("Require");
if (require != null)
{
// if this require directory exists, add this to set only
// if this exists.
path1 = dirpath + "\\" + require.InnerText;
if (Directory.Exists(path1) == false) req = false;
}
if (excpt == false && req == true)
{
XmlElement nm = (XmlElement) par.SelectSingleNode("MenuName");
long flags=0L;
// bug fix B2006-045
// need to convert long folder/file names to short (8.3)
ShortName sname = new ShortName(dirpath);
bool hasSec = usrRunTime.sec.ProcSetHasSecurity(plntsecindx, Path.GetFileName(sname.ShortFileName));
// bool hasSec = usrRunTime.sec.ProcSetHasSecurity(plntsecindx, dirname);
if (this.usrRunTime.sec==null) flags=Security.SUPERACCESS;
else if (hasSec) flags = usrRunTime.sec.GetProcSecurity(sname.ShortFileName);
// else if (hasSec) flags = usrRunTime.sec.GetProcSecurity(dirpath);
if((hasSec && flags!=0L) || (!hasSec&&!usrRunTime.sec.BlockAccess()))
{
CreateProcSet(dirpath, nm, dirname, flags);
return true;
}
}
}
}
return false;
}
// This method processes through the SubDirSearch xmlelement tree in
// menuwin2.xml to see if the input procedure set directory has valid
// procedure set subdirectories. Arguments are:
// subtop is xmlelement for the SubDirSearch in menuwin2.xml, dir is actual
// procset directory name (for example, procs, proc000.dvt, etc) and
// dname is the name to be used for the directory name in the menuwin2.xml
// file under the SubDirSearch xmlelement tree (for example, procs, *.dvt, etc)
private bool ProcessSubDir(XmlElement subtop, string dri, string dname, int plntsecindx)
{
XmlNodeList nodeList;
string xp = "descendant::ProcSet[Dir = \'" + dname + "\']";
try
{
nodeList = subtop.SelectNodes(xp);
// for each possible subdirectory for this directory, see if it
// exists.
foreach (XmlNode subdirname in nodeList)
{
XmlElement subdele=(XmlElement)subdirname;
XmlNodeList FnodeList = subdirname.SelectNodes("ProcFile");
// see if the files listed exist, if so, add them to the
// plant procset list.
foreach (XmlNode dirnd in FnodeList)
{
XmlElement dele=(XmlElement)dirnd;
string dirpath = _Location + "\\" + dri;
if (File.Exists(dirpath+"\\"+dirnd.InnerText))
{
XmlElement nm = (XmlElement) subdirname.SelectSingleNode("MenuName");
string subdir = dirnd.InnerText.Substring(0,dirnd.InnerText.LastIndexOf("\\"));
long flags=0L;
bool hasSec = usrRunTime.sec.ProcSetHasSecurity(plntsecindx, dri+"\\"+subdir);
if (this.usrRunTime.sec==null) flags=Security.SUPERACCESS;
else if (hasSec) flags = usrRunTime.sec.GetProcSecurity(dirpath + "\\" + subdir);
if((hasSec && flags!=0L) || (!hasSec&&!usrRunTime.sec.BlockAccess()))
CreateProcSet(dirpath+"\\"+subdir, nm, dri, flags);
}
break; // out of file check foreach
}
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
return false;
}
return true;
}
// Using the menuwin2.xml file, read in child list by seeing which
// directories (proc sets) are contained in this vexxx directory.
public override bool Read(bool ChkForChldOnly)
{
bool didone;
Cursor.Current = Cursors.WaitCursor;
// using the . Then do exist tests to see if they
// exist on this datapath.
usrRunTime.LoadMenuWin2();
XmlDocument xmldoc = usrRunTime.menuwin2XML.GetXmlDoc();
XmlElement top = (XmlElement) xmldoc.FirstChild;
XmlElement sys = (XmlElement) top.SelectSingleNode("PlantAttach");
XmlElement subtop = (XmlElement) top.SelectSingleNode("SubDirSearch");
DirectoryInfo cur = new DirectoryInfo(_Location);
DirectoryInfo[] diArr = cur.GetDirectories();
int plntsecindx = usrRunTime.sec.GetPlantSecurityIndex(_Location);
foreach (DirectoryInfo dri in diArr)
{
XmlNodeList nodeList;
string dname = null;
int indx;
if ((indx=dri.Name.IndexOf("."))>-1)
{
//must be *.prc, *.bck, *.dvt, *.sl?
if (indx+4<=dri.Name.Length)
{
dname = "*." + dri.Name.Substring(indx+1,3).ToLower();
if (dname.StartsWith("*.sl"))
dname = dname.Substring(0,4) + "?";
}
else
dname = null;
}
else if ((indx=dri.Name.IndexOf("'"))>-1)
{
// bug fix B2006-047
// if not a .PRC folder, then we get an error looking up
// the directory name in XML (if it has an ' in the name)
dname = null;
}
else
{
dname = dri.Name.ToLower();
}
if (dname!=null)
{
string xp = "descendant::ProcSet[Dir = \'" + dname + "\']";
try
{
nodeList = sys.SelectNodes(xp);
foreach (XmlNode dirname in nodeList)
{
XmlElement dele=(XmlElement)dirname;
didone = ProcessDirName(dele, dri.Name, plntsecindx);
if (Children.Count > 0 && ChkForChldOnly)
{
Cursor.Current = Cursors.Default;
return true;
}
// if a directory was found, see if any
// subdirectories exist that need added too.
bool didsub = false;
if (didone) didsub = ProcessSubDir(subtop, dri.Name, dname, plntsecindx);
}
}
catch (Exception e)
{
MessageBox.Show(e.Message.ToString());
Cursor.Current = Cursors.Default;
return false;
}
}
}
// if no children, change icon to empty (unless it has a lock icon)
if (Children.Count <=0 && Lock.LockStatus == VENetwork.Status.NoLock) icon = iconStates[(int)VEO_IconStates.Empty];
Cursor.Current = Cursors.Default;
return true;
}
// write out change (modification of title for plant) for plant to
// the menuwin.xml file
public override bool Write()
{
string newtitle=null;
if (changeTitle)
{
newtitle = tmpTitle;
bool success = usrRunTime.ModMenuWin(newtitle, this._Title);
if (success==false)
{
MessageBox.Show("Could not modify title for the plant.");
return false;
}
MessageBox.Show("Please send \\ve-proms\\menuwin & \\ve-proms\\menuwin.xml files to Volian.");
_Title=newtitle;
changeTitle=false;
}
return true;
}
// create a new proc set object (child for this plant)
public override Object MakeNewChild()
{
if (!isOpen)Open();
VEO_ProcSet ps = new VEO_ProcSetN(usrRunTime,null,_Location);
return ps;
}
// save a new proc set (child for this plant)
public override bool SaveChild(Object obj)
{
VEO_ProcSetN ps = (VEO_ProcSetN) obj;
// check for valid child
bool valid = ps.IsValid();
if (valid == false) return false;
valid = ps.SaveNew("dummy");
if (valid == true)
{
// add this item to this plants list of children.
Children.Add((VEO_ProcSet)obj);
ps.parentObj=this;
ps._Location = this._Location + "\\" + ps._Location;
ps.icon=iconStates[0];
// if this plant's icon is 'empty', change it to either lock (if locked),
// or to not empty.
icon = iconStates[(int)Lock.LockStatus];
IsEmpty=false;
}
return valid;
}
// save a new plant directory
public override bool SaveNew(string pth)
{
// check for non-empty data.
if (tmpLocation == null || tmpLocation == "" || tmpTitle == null || tmpTitle == "")
{
MessageBox.Show("Need to fill in all data.");
return false;
}
// for this new plant, make the directory and write out
// to the menuwin & menuwin.xml files.
// if using the file browser dialog, the drive may be included, if so
// check that the directory matches the datapath.
int slash = tmpLocation.LastIndexOf("\\");
if (slash>0)
{
string drvtmp = tmpLocation.Substring(0,slash+1);
ShortName sname = new ShortName(drvtmp);
string drv=sname.ShortFileName;
sname = null;
if (drv.ToUpper() != pth.ToUpper())
{
MessageBox.Show("Invalid path, directory must match datapath");
return false;
}
// remove the drive part of the path, it's added back later.
tmpLocation = tmpLocation.Substring(slash+1,tmpLocation.Length-(slash+1));
}
// check for ve*
if (tmpLocation.Substring(0,2).ToUpper() != "VE")
{
MessageBox.Show("First two characters must be 'VE' for new plant directory name.");
return false;
}
// also check that the name is not greater than 8 characters (an old 16-bit hangover)
if (tmpLocation.Length>8)
{
MessageBox.Show("Directory/plant name must be 8 characters or less.");
return false;
}
// make path to new directory & check for existence.
string curpath=null;
curpath = pth + "\\" + this.tmpLocation;
DirectoryInfo cur = new DirectoryInfo(curpath);
if (cur.Exists )
{
DirectoryInfo[] di = cur.GetDirectories("*");
FileInfo[] fi = cur.GetFiles("*");
if (di.Length>0 || fi.Length>0)
{
MessageBox.Show("The plant directory you specified already exists & has contents. Enter a different name.");
return false;
}
}
// if the directory exists & it is already in the menu file, it didn't succeed
// in adding the new item.
if (cur.Exists && (usrRunTime.IsInMenuWin(this.tmpLocation)!=0))
{
MessageBox.Show("The plant directory you specified already exists and the plant name exists in the menu files.");
return false;
}
try
{
if (cur.Exists == false)cur.Create();
}
catch (Exception e)
{
MessageBox.Show("Error creating directory: " + e.Message);
return false;
}
// now add to end of menuwin & menuwin.xml.
bool success = usrRunTime.AddToMenuWin(this.tmpTitle,this.tmpLocation);
if (success==false)
{
MessageBox.Show("Could not add directory to ve-proms menuing files. Could not create plant directory.");
cur.Delete();
return false;
}
MessageBox.Show("The VE-PROMS Security Access Module (VESAM) may need to be used to set permissions to access the new plant.");
_Title=tmpTitle;
_Location=tmpLocation;
changeTitle=false;
changeLocation=false;
// set a security flag for this. Cases could be that there is no security in vesam,
// that it has security in vesam, though it didn't exist for this user until now,
// or the user could be super user.
accessFlags=0L;
int idx = usrRunTime.sec.GetPlantSecurityIndex(curpath);
accessFlags = usrRunTime.sec.GetPlantSecurity(idx);
return true;
}
public override void DoListView(ListView veoListView)
{
ListViewItem item=null;
veoListView.Columns.Add("Location", 120, HorizontalAlignment.Left);
veoListView.Columns.Add("Title", 300, HorizontalAlignment.Left);
for (int i=0; i<Children.Count; i++)
{
VEO_ProcSet ps = (VEO_ProcSet) Children[i];
item = new ListViewItem(ps._Location,ps.icon);
item.Tag = ps;
item.SubItems.Add(ps._Title);
veoListView.Items.Add(item);
}
}
public override bool CollapseSibling()
{
if (!usrRunTime.InMultiUserMode) return false;
return true;
}
public override bool mnuAllowLckDB()
{
if (!usrRunTime.InMultiUserMode) return false;
//if (amILockedByMe()==true) return false;
if (Lock.LockStatus==VENetwork.Status.LockedByOther)return false;
// if there are no children, allow a lock in case the user is creating a plant level
// with procedure set
if (this.Children.Count==0) return true;
if ((accessFlags&Security.LOCKSET)==Security.LOCKSET && Lock.LockStatus==VENetwork.Status.NoLock) return true;
return false;
}
public override bool mnuAllowUnlckDB()
{
if (!usrRunTime.InMultiUserMode) return false;
if ((accessFlags&Security.LOCKSET)==Security.LOCKSET&&(Lock.LockStatus==VENetwork.Status.Locked||
Lock.LockStatus==VENetwork.Status.LockPending)) return true;
return false;
}
public override bool mnuAllowDelete()
{
if (amILockedByMe()==false) return false;
if(usrRunTime.sec.SystemAdminFlag) return true;
return false;
}
public override bool mnuAllowNew()
{
if (amILockedByMe()==false) return false;
if (usrRunTime.sec.PermissionToManageFlag) return true;
return false;
}
public override bool canEdit()
{
if (amILockedByMe()==false) return false;
if(usrRunTime.sec.SystemAdminFlag) return true;
return false;
}
}
// the following class is used to support the New plant option from the 'Properties'
// dialog by making location to be editable.
class VEO_PlantN : VEO_Plant
{
public VEO_PlantN(UserRunTime iusrRunTime, string ititle, string ipath)
: base(iusrRunTime, ititle, ipath)
{
isNew=true;
}
// this method is used so that if a new datapath is created, it is associated
// with editable properties (such as path). When the object exists this is
// not editable. So when a new object is created, if it's successful, it's
// copied to an object which is not editable for the treeview & any further
// operations.
public override Object Copy()
{
VEO_Plant plnt = new VEO_Plant(usrRunTime,this._Title,this._Location);
plnt.parentObj = this.parentObj;
plnt.accessFlags = this.accessFlags;
return (Object) plnt;
}
public void SaveFields()
{
_Location=tmpLocation;
_Title=tmpTitle;
changeLocation=false;
changeTitle=false;
}
[Description("Location"),Category("Plant"),ReadOnly(false),EditorAttribute(typeof(VECreateFolderBrowserDlg), typeof(System.Drawing.Design.UITypeEditor))]public new string Location
{
get
{
if (!changeLocation)
return _Location;
else
return tmpLocation;
}
set
{
changeLocation=true;
tmpLocation=value;
}
}
}
}