001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.woody.binding;
018:
019: import org.apache.avalon.framework.logger.LogEnabled;
020: import org.apache.avalon.framework.logger.Logger;
021: import org.apache.cocoon.woody.util.DomHelper;
022: import org.w3c.dom.Element;
023:
024: /**
025: * Abstract base class enabling logging and supporting the intrepretation of
026: * common configuration settings on all specific implementations of
027: * {@link org.apache.cocoon.woody.binding.JXPathBindingBase}.
028: *
029: * Common supported configurations:
030: * <ul>
031: * <li>Attribute direction="load|save|both": {@link #getCommonAttributes(Element)}</li>
032: * </ul>
033: *
034: * @version CVS $Id: JXPathBindingBuilderBase.java 433543 2006-08-22 06:22:54Z crossley $
035: */
036: public abstract class JXPathBindingBuilderBase implements LogEnabled {
037:
038: private Logger logger;
039:
040: /**
041: * Receives the Avalon logger to use.
042: */
043: public void enableLogging(Logger logger) {
044: this .logger = logger;
045: if (logger.isDebugEnabled()) {
046: logger.debug("JXPathBindingBuilderBase got logger...");
047: }
048: }
049:
050: /**
051: * Makes the logger available to the subclasses.
052: * @return Logger
053: */
054: protected Logger getLogger() {
055: return this .logger;
056: }
057:
058: /**
059: * Builds a configured binding object based on the configuration as
060: * described in the bindingElement. The BuilderMap can be used to
061: * find appropriate builders for possible subBinders.
062: *
063: * @param bindingElm
064: * @param assistant
065: * @return JXPathBindingBase
066: */
067: public abstract JXPathBindingBase buildBinding(Element bindingElm,
068: JXPathBindingManager.Assistant assistant)
069: throws BindingException;
070:
071: /**
072: * Helper method for interpreting the common attributes which are supported
073: * on each of the Bindings. These are
074: * <br>
075: * <code>@direction</code> can hold one of the following values:
076: * <ol><li><code>'load'</code>: This binding will only load.</li>
077: * <li><code>'save'</code>: This binding will only save.</li>
078: * <li><code>'both'</code>: This binding will perform both operations.</li>
079: * </ol>
080: * <br>
081: * <code>@lenient</code> can either be:
082: * <ol><li><code>'true'</code>: This binding will set the jxpath context to
083: * be lenient towards the usage of inexisting paths on the back-end model.</li>
084: * <li><code>'false'</code>: This binding will set the jxpath context to be
085: * strict and throwing exceptions for the usage of inexisting paths on the
086: * back-end model.</li>
087: * <li><code>(unset)</code>: This binding will not change the leniency behaviour
088: * on the jxpath this binding receives from his parent binding.</li>
089: * </ol>
090: * @param bindingElm
091: * @return an instance of CommonAttributes
092: * @throws BindingException
093: */
094: static CommonAttributes getCommonAttributes(Element bindingElm)
095: throws BindingException {
096: try {
097: //TODO: should we eventually remove this?
098: //throw an error if people are still using the old-style @read-only or @readonly
099: if (DomHelper.getAttributeAsBoolean(bindingElm, "readonly",
100: false)) {
101: throw new BindingException(
102: "Error in binding file "
103: + DomHelper.getLocation(bindingElm)
104: + "\nThe usage of the attribute @readonly has been deprecated in favour of @direction.");
105: }
106: if (DomHelper.getAttributeAsBoolean(bindingElm,
107: "read-only", false)) {
108: throw new BindingException(
109: "Error in binding file "
110: + DomHelper.getLocation(bindingElm)
111: + "\nThe usage of the attribute @read-only has been deprecated in favour of @direction.");
112: }
113:
114: String direction = DomHelper.getAttribute(bindingElm,
115: "direction", "both");
116:
117: String leniency = DomHelper.getAttribute(bindingElm,
118: "lenient", null);
119:
120: return new CommonAttributes(direction, leniency);
121: } catch (BindingException e) {
122: throw e;
123: } catch (Exception e) {
124: throw new BindingException(
125: "Error building binding defined at "
126: + DomHelper.getLocation(bindingElm), e);
127: }
128: }
129:
130: /**
131: * CommonAttributes is a simple helper class for holding the distinct data
132: * member fields indicating the activity of the sepearate load and save
133: * actions of a given binding.
134: */
135: static class CommonAttributes {
136: /**
137: * Flag which controls whether a binding is active during loading.
138: */
139: final boolean loadEnabled;
140: /**
141: * Flag which controls whether a binding is active during saving.
142: */
143: final boolean saveEnabled;
144: final Boolean leniency;
145:
146: final static CommonAttributes DEFAULT = new CommonAttributes(
147: true, true, null);
148:
149: CommonAttributes(String direction, String leniency) {
150: this (isLoadEnabled(direction), isSaveEnabled(direction),
151: decideLeniency(leniency));
152: }
153:
154: CommonAttributes(boolean loadEnabled, boolean saveEnabled,
155: Boolean leniency) {
156: this .loadEnabled = loadEnabled;
157: this .saveEnabled = saveEnabled;
158: this .leniency = leniency;
159: }
160:
161: /**
162: * Interpretes the value of the direction attribute into activity of the load action.
163: * @param direction
164: * @return true if direction is either set to "both" or "load"
165: */
166: private static boolean isLoadEnabled(String direction) {
167: return "both".equals(direction) || "load".equals(direction);
168: }
169:
170: /**
171: * Interpretes the value of the direction attribute into activity of the save action.
172: * @param direction value of the @direction attribute
173: * @return true if direction is either set to "both" or "save"
174: */
175: private static boolean isSaveEnabled(String direction) {
176: return "both".equals(direction) || "save".equals(direction);
177: }
178:
179: /**
180: * Interpretes the value of the lenient attribute into a Boolean object
181: * allowing three-state logic (true/false/unset)
182: * @param leniency value of the @lenient attribute
183: * @return null if the leniency parameter is String, otherwise the
184: */
185: private static Boolean decideLeniency(String leniency) {
186: if (leniency == null) {
187: return null;
188: }
189: return new Boolean(leniency);
190: }
191: }
192: }
|