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.forms.binding;
018:
019: import org.apache.avalon.framework.CascadingRuntimeException;
020:
021: import org.apache.cocoon.forms.formmodel.Widget;
022: import org.apache.cocoon.util.ClassUtils;
023:
024: import org.apache.commons.jxpath.AbstractFactory;
025: import org.apache.commons.jxpath.JXPathContext;
026: import org.apache.commons.jxpath.Pointer;
027:
028: /**
029: * ContextJXPathBinding provides an implementation of a {@link Binding}
030: * that narrows the binding scope to some xpath-context on the target
031: * objectModel to load and save from.
032: *
033: * @version $Id: ContextJXPathBinding.java 517733 2007-03-13 15:37:22Z vgritsenko $
034: */
035: public class ContextJXPathBinding extends ComposedJXPathBindingBase {
036:
037: /**
038: * the relative contextPath for the sub-bindings of this context
039: */
040: private final String xpath;
041:
042: /**
043: * The name of a factory class for building intermediate elements. Must implement
044: * {@link org.apache.commons.jxpath.AbstractFactory}.
045: */
046: private AbstractFactory factory;
047:
048: /**
049: * Constructs ContextJXPathBinding for the specified xpath sub-context
050: */
051: public ContextJXPathBinding(
052: JXPathBindingBuilderBase.CommonAttributes commonAtts,
053: String contextPath, JXPathBindingBase[] childBindings) {
054: super (commonAtts, childBindings);
055: this .xpath = contextPath;
056: }
057:
058: /**
059: * Constructs ContextJXPathBinding for the specified xpath sub-context and optional JXPath factory class.
060: */
061: public ContextJXPathBinding(
062: JXPathBindingBuilderBase.CommonAttributes commonAtts,
063: String contextPath, String factoryClassName,
064: JXPathBindingBase[] childBindings) {
065: super (commonAtts, childBindings);
066: this .xpath = contextPath;
067: if (factoryClassName != null) {
068: try {
069: this .factory = (AbstractFactory) ClassUtils
070: .newInstance(factoryClassName);
071: } catch (Exception e) {
072: throw new CascadingRuntimeException(
073: "Cannot create an instance of "
074: + factoryClassName, e);
075: }
076: }
077: }
078:
079: public String getFactoryClassName() {
080: return this .factory == null ? null : this .factory.getClass()
081: .getName();
082: }
083:
084: /**
085: * Actively performs the binding from the ObjectModel wrapped in a jxpath
086: * context to the CocoonForm.
087: */
088: public void doLoad(Widget frmModel, JXPathContext jxpc)
089: throws BindingException {
090: Pointer ptr = jxpc.getPointer(this .xpath);
091: if (ptr.getNode() != null) {
092: JXPathContext subContext = jxpc.getRelativeContext(ptr);
093: super .doLoad(frmModel, subContext);
094: if (getLogger().isDebugEnabled()) {
095: getLogger().debug("done loading " + this );
096: }
097: } else {
098: if (getLogger().isDebugEnabled()) {
099: getLogger()
100: .debug("non-existent path: skipping " + this );
101: }
102: }
103: }
104:
105: /**
106: * Actively performs the binding from the CocoonForm to the ObjectModel
107: * wrapped in a jxpath context.
108: */
109: public void doSave(Widget frmModel, JXPathContext jxpc)
110: throws BindingException {
111: if (this .factory != null) {
112: jxpc.setFactory(this .factory);
113: }
114: Pointer ptr = jxpc.getPointer(this .xpath);
115: if (ptr.getNode() == null) {
116: jxpc.createPath(this .xpath);
117: // Need to recreate the pointer after creating the path
118: ptr = jxpc.getPointer(this .xpath);
119: }
120: JXPathContext subContext = jxpc.getRelativeContext(ptr);
121: super .doSave(frmModel, subContext);
122: if (getLogger().isDebugEnabled()) {
123: getLogger().debug("done saving " + this );
124: }
125: }
126:
127: /** To allow child classes to know which path they bind to */
128: public String getXPath() {
129: return this .xpath;
130: }
131:
132: public String toString() {
133: return "ContextJXPathBinding [xpath=" + this .xpath + "]";
134: }
135: }
|