001 package com.oxygenxml.validate.nvdl; 002 003 import com.thaiopensource.util.Equal; 004 005 import java.util.Vector; 006 import java.util.Enumeration; 007 008 /** 009 * Stores mode usage information. 010 */ 011 class ModeUsage { 012 /** 013 * The use mode. 014 */ 015 private Mode mode; 016 /** 017 * The current mode used until now. 018 */ 019 final Mode currentMode; 020 021 /** 022 * Modes depending on context. 023 */ 024 private ContextMap modeMap; 025 026 /** 027 * 028 */ 029 private int attributeProcessing = -1; 030 031 /** 032 * Creates a use mode. 033 * @param mode The mode to be used. 034 * @param currentMode The mode used until the new mode. 035 */ 036 ModeUsage(Mode mode, Mode currentMode) { 037 this(mode, currentMode, null); 038 } 039 040 /** 041 * Creates a use mode. 042 * @param mode The mode to be used. 043 * @param currentMode The mode used until now. 044 * @param modeMap Modes to be used depending on context. 045 */ 046 private ModeUsage(Mode mode, Mode currentMode, ContextMap modeMap) { 047 this.mode = mode; 048 this.currentMode = currentMode; 049 this.modeMap = modeMap; 050 } 051 052 /** 053 * Gets a new mode usage with a different current mode 054 * but with the same mode and modeMap as this one. 055 * @param currentMode The new current mode. 056 * @return A new mode usage with the changed current mode. 057 */ 058 ModeUsage changeCurrentMode(Mode currentMode) { 059 return new ModeUsage(mode, currentMode, modeMap); 060 } 061 062 /** 063 * Check to see if this mode usage is equals with another mode usage. 064 */ 065 public boolean equals(Object obj) { 066 if (!(obj instanceof ModeUsage)) 067 return false; 068 ModeUsage other = (ModeUsage)obj; 069 return this.mode == other.mode && this.currentMode == other.currentMode && Equal.equal(this.modeMap, other.modeMap); 070 } 071 072 /** 073 * Gets a hash code for this mode usage. 074 */ 075 public int hashCode() { 076 int hc = mode.hashCode() ^ currentMode.hashCode(); 077 if (modeMap != null) 078 hc ^= modeMap.hashCode(); 079 return hc; 080 } 081 082 /** 083 * Resolves the Mode.CURRENT to the currentMode for this mode usage. 084 * If not Mode.CURRENT passed as argument then the same mode is returned. 085 * @param mode The mode to be resolved. 086 * @return Either the current mode mode usage or the same mode passed as argument. 087 */ 088 private Mode resolve(Mode mode) { 089 if (mode == Mode.CURRENT) { 090 return currentMode; 091 } 092 if (mode.isAnonymous() && !mode.isDefined()) { 093 return currentMode; 094 } 095 return mode; 096 } 097 098 /** 099 * Get the maximum attribute processing value from the default mode and 100 * from all the modes specified in the contexts. 101 * @return The attribute processing value. 102 */ 103 int getAttributeProcessing() { 104 if (attributeProcessing == -1) { 105 attributeProcessing = resolve(mode).getAttributeProcessing(); 106 if (modeMap != null) { 107 for (Enumeration en = modeMap.values(); 108 en.hasMoreElements() 109 && attributeProcessing != Mode.ATTRIBUTE_PROCESSING_FULL;) 110 attributeProcessing = Math.max(resolve((Mode)en.nextElement()).getAttributeProcessing(), 111 attributeProcessing); 112 } 113 } 114 return attributeProcessing; 115 } 116 117 /** 118 * Check if we have context dependent modes. 119 * @return true if the modeMap exists. 120 */ 121 boolean isContextDependent() { 122 return modeMap != null; 123 } 124 125 /** 126 * Get the mode to be used for a specific context. 127 * @param context The current context. 128 * @return A mode. 129 */ 130 Mode getMode(Vector context) { 131 // first look in the modeMap if exists. 132 if (modeMap != null) { 133 Mode m = (Mode)modeMap.get(context); 134 if (m != null) 135 return resolve(m); 136 } 137 // if no modeMap or no context specific mode found then 138 // return the default mode for this mode usage. 139 return resolve(mode); 140 } 141 142 /** 143 * Adds a new context (isRoot, path --> mode). 144 * @param isRoot Flag indicating that the path starts or not with / 145 * @param names The local names that form the path. 146 * @param mode The mode for this path. 147 * @return true if we do not have a duplicate path. 148 */ 149 boolean addContext(boolean isRoot, Vector names, Mode mode) { 150 if (modeMap == null) 151 modeMap = new ContextMap(); 152 return modeMap.put(isRoot, names, mode); 153 } 154 }