aoqi@0: /* aoqi@0: * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: package com.sun.tools.internal.xjc.reader.xmlschema; aoqi@0: aoqi@0: import java.util.Collection; aoqi@0: aoqi@0: import com.sun.tools.internal.xjc.model.CPropertyInfo; aoqi@0: import com.sun.tools.internal.xjc.model.Multiplicity; aoqi@0: import com.sun.tools.internal.xjc.reader.RawTypeSet; aoqi@0: import com.sun.tools.internal.xjc.reader.gbind.ConnectedComponent; aoqi@0: import com.sun.tools.internal.xjc.reader.gbind.Element; aoqi@0: import com.sun.tools.internal.xjc.reader.gbind.Expression; aoqi@0: import com.sun.tools.internal.xjc.reader.gbind.Graph; aoqi@0: import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty; aoqi@0: import com.sun.xml.internal.bind.v2.model.core.WildcardMode; aoqi@0: import com.sun.xml.internal.xsom.XSParticle; aoqi@0: aoqi@0: /** aoqi@0: * {@link ParticleBinder} that uses {@link ExpressionBuilder} et al aoqi@0: * for better, more intuitive (but non spec-conforming) binding. aoqi@0: * aoqi@0: * @author Kohsuke Kawaguchi aoqi@0: */ aoqi@0: final class ExpressionParticleBinder extends ParticleBinder { aoqi@0: public void build(XSParticle p, Collection forcedProps) { aoqi@0: // this class isn't about spec conformance, but aoqi@0: // for the ease of use. aoqi@0: // so we don't give a damn about 'forcedProps'. aoqi@0: // although, for a future note, it's conceivable to expand aoqi@0: // the binding algorithm to cover this notion. aoqi@0: aoqi@0: Expression tree = ExpressionBuilder.createTree(p); aoqi@0: Graph g = new Graph(tree); aoqi@0: for (ConnectedComponent cc : g) { aoqi@0: buildProperty(cc); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Builds a property ouf ot a connected component. aoqi@0: */ aoqi@0: private void buildProperty(ConnectedComponent cc) { aoqi@0: StringBuilder propName = new StringBuilder(); // property name aoqi@0: int nameTokenCount = 0; // combine only up to 3 aoqi@0: aoqi@0: RawTypeSetBuilder rtsb = new RawTypeSetBuilder(); aoqi@0: for (Element e : cc) { aoqi@0: GElement ge = (GElement)e; aoqi@0: aoqi@0: if(nameTokenCount<3) { aoqi@0: if(nameTokenCount!=0) aoqi@0: propName.append("And"); aoqi@0: propName.append(makeJavaName(cc.isCollection(),ge.getPropertyNameSeed())); aoqi@0: nameTokenCount++; aoqi@0: } aoqi@0: aoqi@0: if(e instanceof GElementImpl) { aoqi@0: GElementImpl ei = (GElementImpl) e; aoqi@0: rtsb.elementDecl(ei.decl); aoqi@0: continue; aoqi@0: } aoqi@0: if(e instanceof GWildcardElement) { aoqi@0: GWildcardElement w = (GWildcardElement)e; aoqi@0: rtsb.getRefs().add(new RawTypeSetBuilder.WildcardRef( aoqi@0: w.isStrict() ? WildcardMode.STRICT : WildcardMode.SKIP)); aoqi@0: continue; aoqi@0: } aoqi@0: assert false : e; // no other kind should be here aoqi@0: } aoqi@0: aoqi@0: Multiplicity m = Multiplicity.ONE; aoqi@0: if(cc.isCollection()) aoqi@0: m = m.makeRepeated(); aoqi@0: if(!cc.isRequired()) aoqi@0: m = m.makeOptional(); aoqi@0: aoqi@0: RawTypeSet rts = new RawTypeSet(rtsb.getRefs(),m); aoqi@0: aoqi@0: XSParticle p = findSourceParticle(cc); aoqi@0: aoqi@0: BIProperty cust = BIProperty.getCustomization(p); aoqi@0: CPropertyInfo prop = cust.createElementOrReferenceProperty( aoqi@0: propName.toString(), false, p, rts ); aoqi@0: getCurrentBean().addProperty(prop); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Finds a {@link XSParticle} that can serve as the representative property of aoqi@0: * the given {@link ConnectedComponent}. aoqi@0: * aoqi@0: * The representative property is used for reporting an error location and aoqi@0: * taking {@link BIProperty} customization. Right now, the algorithm is just pick aoqi@0: * the first one with {@link BIProperty}, but one can think of a better algorithm, aoqi@0: * such as taking a choice of (A|B) if CC={A,B}. aoqi@0: */ aoqi@0: private XSParticle findSourceParticle(ConnectedComponent cc) { aoqi@0: XSParticle first = null; aoqi@0: aoqi@0: for (Element e : cc) { aoqi@0: GElement ge = (GElement)e; aoqi@0: for (XSParticle p : ge.particles) { aoqi@0: if(first==null) aoqi@0: first = p; aoqi@0: if(getLocalPropCustomization(p)!=null) aoqi@0: return p; aoqi@0: } aoqi@0: // if there are multiple property customizations, aoqi@0: // all but one will be left unused, which will be detected as an error aoqi@0: // later, so no need to check that now. aoqi@0: } aoqi@0: aoqi@0: // if no customization was found, just use the first one. aoqi@0: return first; aoqi@0: } aoqi@0: aoqi@0: public boolean checkFallback(XSParticle p) { aoqi@0: // this algorithm never falls back to 'getContent'. aoqi@0: return false; aoqi@0: } aoqi@0: }