Rev 908 | Blame | Last modification | View Log | RSS feed
package com.erggroup.buildtool.ripple;import java.io.File;import java.sql.SQLException;import java.util.Iterator;import java.util.Vector;import org.apache.log4j.Logger;import com.erggroup.buildtool.smtp.Smtpsend;public class Package{/**name of package, must not contain spaces* @attribute*/String mName = new String();/**package scope* @attribute*/String mExtension = new String();/**instance identifier* @attribute*/String mVersion = new String();/**unique identifier* for daemon builds = mName + mExtension* for escrow builds = mName + mVersion + mExtension* @attribute*/String mAlias = new String();/**clearcase vob location, must not contain spaces* @attribute*/String mLocation = new String();/**clearcase source file instance identifier* @attribute*/String mLabel = new String();/**build standards* @attribute*/Vector<BuildStandard> mBuildStandardCollection = new Vector<BuildStandard>();/**GBE_MACHTYPE used to build generic packages for this baseline* only has meaning in the daemon build, not the escrow build* accessed by BuildStandard::getPlatform, getBuildStandard* @attribute*/public static final String mGenericMachtype = System.getenv("GBE_MACHTYPE");/**build dependencies by package alias* @attribute*/Vector<String> mDependencyCollection = new Vector<String>();/**primary package version key pv_id in database* @attribute*/int mId;/**indication of the nature of change* @attribute*/Package.VersionNumberingStandard mChangeType = new VersionNumberingStandard();/**determines what field is rippled on a package version whose dependencies have changed* @attribute*/Package.VersionNumberingStandard mRippleField = new VersionNumberingStandard();/**interested owners* @attribute*/private Vector<String> mBuildFailureEmailCollection = new Vector<String>();/**when true will trigger unit tests as part of the package build phase in daemon mode* @attribute*/boolean mHasAutomatedUnitTests = false;/**when true, do not ripple this package through packages which are dependent upon it in daemon mode* @attribute*/boolean mAdvisoryRipple = false;/**determines the build file the package is built in, or not* 1 buildfile 1 etc* 0 not yet processed (initial value)* -1 not reproducible* -2 not reproducible on the build platforms configured for this release* -3 do not ripple* -4 directly dependent on package versions not in the baseline* -5 indirectly dependent on package versions which are not reproducible* because of -1, -2 (escrow), -3 (daemon), -4, -6* -6 circular dependency* @attribute*/int mBuildFile = 0;/**build dependencies by package* @attribute*/Vector<Package> mPackageDependencyCollection = new Vector<Package>();/**used for escrow build purposes* set true when a package has been processed* @attribute*/boolean mProcessed = false;/**set true for WIP package versions* only used in daemon mode* @attribute*/boolean mDirectlyPlanned = false;/**set true when it is determined to be ripple built* @attribute*/boolean mIndirectlyPlanned = false;/**non zero instruction number when it is determined to be ripple built by force* @attribute*/int mForcedRippleInstruction = 0;/**non zero instruction number when it is determined to be test built* @attribute*/int mTestBuildInstruction = 0;/**test build email destination* @attribute*/String mTestBuildEmail;/**clearcase vob location, must not contain spaces* @attribute*/String mTestBuildLocation = new String();/**clearcase source file instance identifier* @attribute*/String mTestBuildLabel = new String();/**build standards* @attribute*/Vector<BuildStandard> mTestBuildStandardCollection = new Vector<BuildStandard>();/**build dependencies by package alias* @attribute*/Vector<String> mTestBuildDependencyCollection = new Vector<String>();/**build dependencies by pv_id (-1 or not used for planned dependencies)* @attribute*/Vector<Integer> mDependencyIDCollection = new Vector<Integer>();/**unique pkg_id in the database* used for querying package version existence in the database in daemon mode* @attribute*/int mPid;/**maximum major number supported for determining ripple number* @attribute*/int mMajorLimit;/**maximum minor number supported for determining ripple number* @attribute*/int mMinorLimit;/**maximum patch number supported for determining ripple number* @attribute*/int mPatchLimit;/**maximum build number number supported for determining ripple number* @attribute*/int mBuildLimit;/**Logger* @attribute*/private static final Logger mLogger = Logger.getLogger(Package.class);/**dpkg archive location* @attribute*/public static final String mGbeDpkg = System.getenv("GBE_DPKG");/**deploy archive location* @attribute*/public static final String mGbeDply = System.getenv("GBE_DPLY");/**Exception message used upon detection an archive does not exist* Seems this is a rare but transient and recoverable scenario* @attribute*/public static final String mRecoverable = "dpkg or deploy_archive do not exist, recovery will be attempted";/**true if the package exists in the dpkg or deploy archive* @attribute*/private boolean mArchivalExistence = true;/**when true will trigger source control interaction eg labelling* @attribute*/public boolean mRequiresSourceControlInteraction = true;/**when true has been checked for circular dependency* @attribute*/boolean mCheckedCircularDependency = false;/**when true has circular dependency* @attribute*/boolean mHasCircularDependency = false;/**constructor*/Package(int pv_id, String pkg_name, String v_ext, String alias,String pkg_label, String src_path, char change_type, char ripple_field){mLogger.debug("Package 1: pv_id " + pv_id + " pkg_name " + pkg_name + " v_ext " + v_ext + " alias " + alias + " pkg_label " + pkg_label + " src_path " + src_path + " change_type " + change_type);mId = pv_id;mName = pkg_name;mVersion = "0.0.0000";mExtension = v_ext;mAlias = alias;mLabel = pkg_label;mLocation = src_path;if (change_type == 'M'){// a ripple_field of 'L' indicates this package has limited version numberingmChangeType.setMajor(ripple_field == 'L' ? true : false);}else if (change_type == 'N'){mChangeType.setMinor(ripple_field == 'L' ? true : false);}else{mChangeType.setPatch(ripple_field == 'L' ? true : false);}}/**constructor*/Package(int pv_id, String pkg_name, String pkg_version, String v_ext,String alias, String pkg_label, String src_path,char ripple_field){mLogger.debug("Package 2: pv_id " + pv_id + " pkg_name " + pkg_name + " pkg_version " + pkg_version + " v_ext " + v_ext + " alias " + alias + " pkg_label " + pkg_label + " src_path " + src_path + " ripple_field " + ripple_field);mId = pv_id;mName = pkg_name;mVersion = pkg_version;int endindex = mVersion.length() - v_ext.length();if ( endindex > 0 ){mVersion = mVersion.substring(0, endindex);}mExtension = v_ext;mAlias = alias;mLabel = pkg_label;mLocation = src_path;// setBuild is the defaultif (ripple_field == 'M'){mRippleField.setMajor();}else if (ripple_field == 'm'){mRippleField.setMinor();}else if (ripple_field == 'p'){mRippleField.setPatch();}else if (ripple_field == 'L'){mRippleField.setLimit();}}/**constructor*/Package(){mLogger.debug("Package 3");mId = 0;mName = "null";mExtension = "null";mAlias = "null";mLabel = "null";mLocation = "null";}/**constructor for test build purposes*/Package(String pkg_name, String v_ext, String alias,String pkg_label, String src_path, int testBuildInstruction, String email){mLogger.debug("Package 4: pkg_name " + pkg_name + " v_ext " + v_ext + " alias " + alias + " pkg_label " + pkg_label + " src_path " + src_path);// don't need pv_idmId = -1;mName = pkg_name;// avoid interaction with real versionsmVersion = "0.0.0000";mExtension = v_ext;mAlias = alias;mTestBuildInstruction = testBuildInstruction;mTestBuildEmail = email;mTestBuildLocation = src_path;mTestBuildLabel = pkg_label;}/**constructor for unit test purposes*/public Package(ReleaseManager rm, String version, int majorLimit, int minorLimit, int patchLimit, int buildNumberLimit){mId = -1;mRippleField.setLimit();mVersion = version;mMajorLimit = majorLimit;mMinorLimit = minorLimit;mPatchLimit = patchLimit;mBuildLimit = buildNumberLimit;try{mId = applyPV( rm, 0 );}catch(Exception e){}}/**accessor for unit test purposes*/public int getId(){return mId;}/**accessor for unit test purposes*/public String getVersion(){return mVersion;}/**returns true if mBuildStandardCollection is not empty*/boolean isReproducible(){mLogger.debug("isReproducible on Package " + mName);boolean retVal = false;if ( mBuildStandardCollection.size() > 0 ){retVal = true;}mLogger.info("isReproducible returned " + retVal);return retVal;}/**returns true if at least one of its BuildStandards has mWin32 or mGeneric true*/boolean isWin32Built(){mLogger.debug("isWin32Built on Package " + mName);boolean retVal = false;for (Iterator<BuildStandard> it = mBuildStandardCollection.iterator(); it.hasNext(); ){BuildStandard buildStandard = it.next();if (buildStandard.getWin32() || buildStandard.getGeneric()){retVal = true;break;}}mLogger.info("isWin32Built returned " + retVal);return retVal;}/**returns true if at least one of its BuildStandards has mSolaris or mGeneric true*/boolean isSolarisBuilt(){mLogger.debug("isSolarisBuilt on Package " + mName);boolean retVal = false;for (Iterator<BuildStandard> it = mBuildStandardCollection.iterator(); it.hasNext(); ){BuildStandard buildStandard = it.next();if (buildStandard.getSolaris() || buildStandard.getGeneric()){retVal = true;break;}}mLogger.info("isSolarisBuilt returned " + retVal);return retVal;}/**returns true if at least one of its BuildStandards has mLinux or mGeneric true*/boolean isLinuxBuilt(){mLogger.debug("isLinuxBuilt on Package " + mName);boolean retVal = false;for (Iterator<BuildStandard> it = mBuildStandardCollection.iterator(); it.hasNext(); ){BuildStandard buildStandard = it.next();if (buildStandard.getLinux() || buildStandard.getGeneric()){retVal = true;break;}}mLogger.info("isLinuxBuilt returned " + retVal);return retVal;}/**returns true if at least one of its BuildStandards has mGeneric true*/boolean isGeneric(){mLogger.debug("isGeneric on Package " + mName);boolean retVal = false;for (Iterator<BuildStandard> it = mBuildStandardCollection.iterator(); it.hasNext(); ){BuildStandard buildStandard = it.next();if (buildStandard.getGeneric()){retVal = true;break;}}mLogger.info("isGeneric returned " + retVal);return retVal;}/**applies the required version number change* returns 0 on success* 1 on cannot work with non standard versioning* 2 on ripple field limitations prevent a ripple build*/int applyPV(ReleaseManager releaseManager, int rtag_id) throws Exception{mLogger.debug("applyPV on Package " + mName);// four scenarios, only applyPV for 3 of them// WIP/test build exists: mDirectlyPlanned == true; mIndirectlyPlanned == true; mArchivalExistence don't care; mForcedRipple don't care - applyPV// Package version is out of date: mDirectlyPlanned == false; mIndirectlyPlanned == true; mArchivalExistence == true; mForcedRipple don't care - applyPV// Forced ripple: mDirectlyPlanned == false; mIndirectlyPlanned == true; mArchivalExistence don't care; mForcedRipple > 0 - applyPV// Package version does not exist: mDirectlyPlanned == false; mIndirectlyPlanned == true; mArchivalExistence == false; mForcedRipple = 0 - do not applyPVif ( !mDirectlyPlanned && mIndirectlyPlanned && !mArchivalExistence && mForcedRippleInstruction == 0 ){// the package has an mIndirectlyPlanned flag set true in daemon mode because the package does not exist in an archive// do not apply a different package versionmLogger.info("applyPV !mDirectlyPlanned && mIndirectlyPlanned && !mArchivalExistence && zero mForcedRippleInstruction on Package " + mName);releaseManager.claimVersion(mPid, mVersion + mExtension, rtag_id);mLogger.info("applyPv returned 0");return 0;}// override - no longer doing a rebuild - version number change from this point onif ( mTestBuildInstruction == 0 ){mRequiresSourceControlInteraction = true;}MutableInt major = new MutableInt();major.value = 0;MutableInt minor = new MutableInt();minor.value = 0;MutableInt patch = new MutableInt();patch.value = 1000;String field[] = mVersion.split("\\D");String nonStandardCotsVersion = "";if ( field.length == 3 ){major.value = Integer.parseInt(field[0]);minor.value = Integer.parseInt(field[1]);patch.value = Integer.parseInt(field[2]);}else{if ( !mChangeType.mMajor &&!mChangeType.mMinor &&!mChangeType.mPatch &&mRippleField.mBuild &&mExtension.compareTo(".cots") == 0 &&field.length > 0 ){// DEVI 52782// allow and work with (ripple build) versions a.b.c.d....xxxx// where xxxx.length > 3String patchStr = field[field.length - 1];int patchLen = patchStr.length();// check patchStr is the last (at least 4) digitsif ( patchLen > 3 && mVersion.substring( mVersion.length() - patchLen, mVersion.length() ).compareTo(patchStr) == 0 ){patch.value = Integer.parseInt(patchStr);nonStandardCotsVersion = mVersion.substring(0, mVersion.length() - patchLen );}}if ( nonStandardCotsVersion.length() == 0 ){// cannot work with non standard versioningmLogger.error("applyPV cannot work with non standard versioning");mLogger.info("applyPv returned 1");return 1;}}if ( nonStandardCotsVersion.length() == 0 &&patch.value < 1000 &&field[2].substring(0, 1).compareTo("0") != 0 ){mLogger.info("applyPV accomodate old style mVersion of the form 1.0.1");patch.value = patch.value * 1000;}// mChangeType overrides mRippleFielddo{if ( mChangeType.mMajor ){if ( !incrementFieldsAccordingToLimits(4, major, minor, patch) ){mLogger.info("applyPv returned 2");return 2;}}else if ( mChangeType.mMinor ){if ( !incrementFieldsAccordingToLimits(3, major, minor, patch) ){mLogger.info("applyPv returned 2");return 2;}}else if ( mChangeType.mPatch ){if ( !incrementFieldsAccordingToLimits(2, major, minor, patch) ){mLogger.info("applyPv returned 2");return 2;}}else{if ( mRippleField.mMajor ){major.value++;mLogger.info("applyPV mRippleField.mMajor " + major.value);minor.value = 0;patch.value = 0;}else if ( mRippleField.mMinor ){minor.value++;mLogger.info("applyPV mRippleField.mMinor " + minor.value);patch.value = 0;}else if ( mRippleField.mPatch ){do{patch.value++;} while ( ( patch.value / 1000 ) * 1000 != patch.value );mLogger.info("applyPV mRippleField.mPatch " + patch.value);}else if ( mRippleField.mBuild ){patch.value++;mLogger.info("applyPV mRippleField.mBuild " + patch.value);}else{if ( !incrementFieldsAccordingToLimits(1, major, minor, patch) ){mLogger.info("applyPv returned 2");return 2;}}}if ( nonStandardCotsVersion.length() == 0 ){mVersion = String.valueOf(major.value) + "." + String.valueOf(minor.value) + ".";}else{mVersion = nonStandardCotsVersion;}if ( patch.value < 10 ){mVersion += "000";}else if ( patch.value < 100 ){mVersion += "00";}else if ( patch.value < 1000 ){mVersion += "0";}mVersion += String.valueOf(patch.value);} while ( exists(releaseManager, rtag_id) );releaseManager.claimVersion(mPid, mVersion + mExtension, rtag_id);mLogger.info("applyPv returned 0");return 0;}/**increments fields according to mRippleField.mLimit if necessary* will apply it to the field passed as follows* 1 = build* 2 = patch* 3 = minor* other = major* returns true on success* false on ripple field limitations prevent a ripple build*/private boolean incrementFieldsAccordingToLimits(int field, MutableInt major, MutableInt minor, MutableInt patch){boolean retVal = true;if (!mChangeType.mLimit && !mRippleField.mLimit){// simple case// no need to take field limits into considerationswitch (field){case 1:// unreachable// the only scenario involving build number manipulation involves the mRippleField.mLimit being setretVal = false;break;case 2:do{patch.value++;} while ( ( patch.value / 1000 ) * 1000 != patch.value );mLogger.info("incrementFieldsAccordingToLimits patch " + patch.value);break;case 3:minor.value++;mLogger.info("incrementFieldsAccordingToLimits minor " + minor.value);patch.value = 0;break;default:major.value++;mLogger.info("incrementFieldsAccordingToLimits major " + major.value);minor.value = 0;patch.value = 0;}}else{// take field limits into considerationboolean changeOccurred = false;boolean incrementField = true;switch (field){case 1:if ( mBuildLimit != 0 ){// increment or reset the patch build numberint buildNumber = patch.value - (patch.value/1000) * 1000;if ( buildNumber < mBuildLimit ){// can increment the patch build numberpatch.value++;mLogger.info("incrementFieldsAccordingToLimits mRippleField.mLimit build number " + patch.value);changeOccurred = true;incrementField = false;}else{if ( mPatchLimit == 0 ){// reset the patch number and patch build numberpatch.value = 0;}}}// no break by designcase 2:if ( mPatchLimit != 0 && incrementField ){// increment or reset the patch numberif ( ( patch.value / 1000 ) < mPatchLimit ){do{patch.value++;} while ( ( patch.value / 1000 ) * 1000 != patch.value );mLogger.info("incrementFieldsAccordingToLimits mRippleField.mLimit patch " + patch.value);changeOccurred = true;incrementField = false;}else{// reset the patch number and patch build numberpatch.value = 0;}}// no break by designcase 3:if ( mMinorLimit != 0 && incrementField ){// increment or reset the minor numberif ( minor.value < mMinorLimit ){minor.value++;patch.value = 0;mLogger.info("incrementFieldsAccordingToLimits mRippleField.mLimit minor " + minor.value);changeOccurred = true;incrementField = false;}else{// reset the minor numberminor.value = 0;}}// no break by designdefault:if ( mMajorLimit != 0 && incrementField ){// increment or reset the major numberif ( major.value < mMajorLimit ){// increment the major numberchangeOccurred = true;major.value++;minor.value = 0;patch.value = 0;mLogger.info("incrementFieldsAccordingToLimits mRippleField.mLimit major " + major.value);}}}if ( !changeOccurred ){// unable to increment a field due to field limitationsmLogger.error("incrementFieldsAccordingToLimits ripple field limitations prevent a ripple build");mLogger.info("incrementFieldsAccordingToLimits returned false");retVal = false;}}return retVal;}/**returns true if the version exists in the dpkg_archive, deploy_archive or release manager database* claims the version in the release manager database*/private boolean exists(ReleaseManager releaseManager, int rtag_id) throws Exception{mLogger.debug("exists 1 on Package " + mName + " version " + mVersion + " extension " + mExtension);boolean retVal = false;if ( !ReleaseManager.mUseDatabase ){mLogger.info("exists 1 !releaseManager.mUseDatabase");}else{retVal = exists();if ( !retVal ){String pkg_version = new String(mVersion);if ( mExtension.length() > 0 ){pkg_version += mExtension;}retVal = releaseManager.queryPackageVersions(mPid, pkg_version);}}mLogger.info("exists 1 returned " + retVal);return retVal;}/**returns true if the dpkg_archive and deploy_archive exist* attempt to recover from their transient loss*/public static boolean recover(){mLogger.debug("recover");boolean retVal = false;String Release = mGbeDpkg;String Deploy = mGbeDply;if (Release != null && Deploy != null){File dpkg = new File(mGbeDpkg);File dply = new File(mGbeDply);if ( dpkg.exists() && dply.exists() ){retVal = true;}}mLogger.info("recover returned " + retVal);return retVal;}/**returns true if the version exists in the dpkg_archive or deploy_archive*/boolean exists()throws Exception{mLogger.debug("exists 2 on Package " + mName);boolean retVal = false;String Release = mGbeDpkg;String Deploy = mGbeDply;if (Release == null || Deploy == null){mLogger.fatal("exists 2 Release == null || Deploy == null");throw new Exception("exists 2 Release == null || Deploy == null");}File dpkg = new File(mGbeDpkg);File dply = new File(mGbeDply);if ( !dpkg.exists() || !dply.exists() ){mLogger.fatal("exists 2 " + mRecoverable);throw new Exception(mRecoverable);}String fs = System.getProperty( "file.separator" );String name = new String(Release);name += fs + mName + fs + mVersion + mExtension;File release = new File(name);if (release.exists()){mLogger.info("exists 2 release.exists()");retVal = true;}if (!retVal && (Release != Deploy)){name = Deploy + fs + mName + fs + mVersion + mExtension;File deploy = new File(name);if (deploy.exists()){mLogger.info("exists 2 deploy.exists()");retVal = true;}}mArchivalExistence = retVal;mLogger.info("exists 2 returned " + retVal);return retVal;}/**returns email information*/String emailInfo( String lf ){String retVal = new String();for (Iterator<String> it = mBuildFailureEmailCollection.iterator(); it.hasNext(); ){String email = it.next();retVal +=" <owner email=\"" + email +"\"/>" + lf;}return retVal;}/**returns email information*/String emailInfoNonAntTask(){String retVal = null;for (Iterator<String> it = mBuildFailureEmailCollection.iterator(); it.hasNext(); ){String email = it.next();if ( retVal == null ){retVal = new String();}else{retVal += ",";}retVal += email;}return retVal;}/**adds email to mBuildFailureEmailCollection if unique*/void addEmail( String email ){boolean alreadyExists = false;for (Iterator<String> it = mBuildFailureEmailCollection.iterator(); it.hasNext(); ){String existingEmail = it.next();if ( existingEmail.compareTo(email) == 0 ){alreadyExists = true;break;}}if ( !alreadyExists ){mBuildFailureEmailCollection.add(email);}}/**accessor method*/void setEmail(){mBuildFailureEmailCollection.clear();addEmail( mTestBuildEmail );}/**accessor method*/void setDependencyCollection(){// does not worry about mPackageDendencyCollection by designmDependencyCollection.clear();for (Iterator<String> it = mTestBuildDependencyCollection.iterator(); it.hasNext(); ){String dependency = it.next();mDependencyCollection.add(dependency);}}/**accessor method*/void setBuildStandardCollection(){mBuildStandardCollection.clear();for (Iterator<BuildStandard> it = mTestBuildStandardCollection.iterator(); it.hasNext(); ){BuildStandard buildStandard = it.next();mBuildStandardCollection.add(buildStandard);}}/**sends email notification and marks the instruction complete in the database*/public void completeTestBuild( String mailServer, String mailSender, ReleaseManager releaseManager, String release, boolean success ) throws SQLException, Exception{mLogger.debug("completeTestBuild");if ( mTestBuildInstruction == 0){return;}String mailBody="Test build issues are identified in preceding build failure email.<p>" +"Release: " + release + "<br>" +"Package: " + mAlias + "<br>" +"Label: " + mLabel + "<br>" +"Location: " + mLocation + "<p>" +"Build dependencies:<p>";for (Iterator<Package> it3 = mPackageDependencyCollection.iterator(); it3.hasNext(); ){Package depend = it3.next();String dependsExtension = depend.mExtension;String dependsVersion = depend.mVersion;if ( dependsExtension.length() > 0 ){dependsVersion += dependsExtension;}mailBody += "\'" + depend.mName + "\',\'" + dependsVersion + "\' <br>";}mailBody += "<br>Build standards:<p>";for (Iterator<BuildStandard> it = mBuildStandardCollection.iterator(); it.hasNext(); ){BuildStandard bs = it.next();String platform = bs.getPlatform(!ReleaseManager.mUseDatabase, false);if ( platform.length() > 0 ){mailBody += platform + ", ";}String standard = bs.getBuildStandard(!ReleaseManager.mUseDatabase, false);if ( standard.length() > 0 ){mailBody += standard + "<br>";}}try{Smtpsend.send(mailServer, // mailServermailSender, // sourceemailInfoNonAntTask(), // targetnull, // ccnull, // bccsuccess == true ? "TEST BUILD COMPLETED SUCCESSFULLY" : "TEST BUILD FAILED", // subjectmailBody, // bodynull // attachment);}catch( Exception e ){}releaseManager.markDaemonInstCompletedConnect(mTestBuildInstruction);}/**returns true if the package has a circular dependency*/public boolean hasCircularDependency(RippleEngine ripEng){mLogger.debug("hasCircularDependency");boolean retVal = detectCircularDependency( mAlias, ripEng );mLogger.info("hasCircularDependency returned " + retVal);return retVal;}/**returns true if the package has a circular dependency*/public boolean detectCircularDependency(String alias, RippleEngine ripEng){mLogger.debug("detectCircularDependency");boolean retVal = false;// if this package has yet to be checked for circular dependencyif ( !mCheckedCircularDependency ){for (Iterator<String> it2 = mDependencyCollection.iterator(); it2.hasNext(); ){String dependencyAlias = it2.next();// check its direct dependencies for an alias matchif ( alias.compareTo( dependencyAlias ) == 0 ){retVal = true;break;}Package dependency = ripEng.findPackage( dependencyAlias );// check its indirect dependencies for an alias matchif ( dependency.detectCircularDependency(alias, ripEng) ){retVal = true;break;}}// mark the check completemCheckedCircularDependency = true;// persist the circular dependency outcomemHasCircularDependency = retVal;}else{// return the persisted circular dependency outcomeretVal = mHasCircularDependency;}mLogger.info("detectCircularDependency 2 returned " + retVal);return retVal;}/**entity class supporting the ERG version numbering standard:* <major>.<minor>.<patch/build>* patch/build is at least a 4 digit number whose last 3 digits represent the build*/public class VersionNumberingStandard{/**in terms of the mChangeType Package field,* when true indicates the contract of the package has changed in a non backwardly compatible manner* in terms of the mRippleField Package field,* when true indicates the major version number will be incremented* @attribute*/private boolean mMajor = false;/**in terms of the mChangeType Package field,* when true indicates the contract of the package has changed in a backwardly compatible manner* in terms of the mRippleField Package field,* when true indicates the minor version number will be incremented* @attribute*/private boolean mMinor = false;/**in terms of the mChangeType Package field,* when true indicates the contract of the package has not changed, but the package has changed internally* in terms of the mRippleField Package field,* when true indicates the minor version number will be incremented* @attribute*/private boolean mPatch = false;/**in terms of the mChangeType Package field,* when true indicates the package has not changed, its dependencies potentially have* in terms of the mRippleField Package field,* when true indicates the build number will be incremented* @attribute*/private boolean mBuild = true;/**in terms of the mChangeType Package field,* when true indicates the major, minor, and patch number will be incremented according to field limits* in terms of the mRippleField Package field,* when true indicates the major, minor, patch and build number will be incremented according to field limits* @attribute*/private boolean mLimit = false;/**constructor*/private VersionNumberingStandard(){mLogger.debug("VersionNumberingStandard");}/**sets mBuild true, mMajor false, mMinor false, mPatch false, mLimit false*/void setBuild(){mLogger.debug("setBuild");mBuild = true;mMajor = false;mMinor = false;mPatch = false;mLimit = false;}/**sets mBuild false, mMajor true, mMinor false, mPatch false, mLimit false*/void setMajor(){mLogger.debug("setMajor");mBuild = false;mMajor = true;mMinor = false;mPatch = false;mLimit = false;}/**sets mBuild false, mMajor true, mMinor false, mPatch false, mLimit limit*/void setMajor( boolean limit ){mLogger.debug("setMajor " + limit);mBuild = false;mMajor = true;mMinor = false;mPatch = false;mLimit = limit;}/**sets mBuild false, mMajor false, mMinor true, mPatch false, mLimit false*/void setMinor(){mLogger.debug("setMinor");mBuild = false;mMajor = false;mMinor = true;mPatch = false;mLimit = false;}/**sets mBuild false, mMajor false, mMinor true, mPatch false, mLimit limit*/void setMinor( boolean limit ){mLogger.debug("setMinor " + limit);mBuild = false;mMajor = false;mMinor = true;mPatch = false;mLimit = limit;}/**sets mBuild false, mMajor false, mMinor false, mPatch true, mLimit false*/void setPatch(){mLogger.debug("setPatch");mBuild = false;mMajor = false;mMinor = false;mPatch = true;mLimit = false;}/**sets mBuild false, mMajor false, mMinor false, mPatch true, mLimit limit*/void setPatch( boolean limit ){mLogger.debug("setPatch");mBuild = false;mMajor = false;mMinor = false;mPatch = true;mLimit = limit;}/**sets mBuild false, mMajor false, mMinor false, mPatch false, mLimit true*/void setLimit(){mLogger.debug("setPatch");mBuild = false;mMajor = false;mMinor = false;mPatch = false;mLimit = true;}}}