📄 structure.java
字号:
package org.ofbiz.rules.engine;
/**
* <p><b>Title:</b> Structure
* <p><b>Description:</b> None
* <p>Copyright (c) 1999 Steven J. Metsker.
* <p>Copyright (c) 2001 The Open For Business Project - www.ofbiz.org
*
* <p>Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* <p>The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* <p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
* OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* <br>
* <p>A Structure is a functor associated with a number of terms;
* a functor can be any object. A term is an object that
* implements the Term interface, including structures and
* variables.
* <p>
* An example of a structure is:
* <blockquote><pre>
* starred(jamesCagney, "Yankee Doodle Dandy", Year)
* </pre></blockquote>
* This structure has the String <code>"starred"</code> as its
* functor. This structure's first term is another structure
* that has "jamesCagney" as its functor and no terms of its own.
* Similarly, the second term is a structure with the functor
* "Yankee Doodle Dandy" and no terms of its own. The third
* term is a variable, Year.
* <p>
* This particular example has two elements that favor a
* parser: the quotes around the film title and the
* capitalization of the variable. When using Structure and
* Variable directly, you do not need the kinds of clues a
* parser needs. So, Yankee Doodle Dandy is just another
* string, whose internal blanks are not at all confusing.
* Further, a variable can have any string as its name, not
* necessarily capitalized.
* <p>
* You can create the starred example with
* <blockquote><pre>
* Structure s = new Structure(
* "starred",
* new Term[]{
* new Structure("jamesCagney"),
* new Structure("Yankee Doodle Dandy"),
* new Variable("Year")});
* </pre></blockquote>
* To be able to prove itself against a program, a structure
* must appear in a Rule. Rules associate like-named variables
* in a "scope", which is essentially a dictionary. A rule
* makes an executable copy of itself by creating a new
* variable dictionary, and by making "consulting" copies of
* its structures.
*
* @author Steven J. Metsker
* @version 1.0
*/
public class Structure implements Term {
protected Object functor;
protected Term[] terms;
/** the empty list singleton */
public final static EmptyList emptyList = new EmptyList();
/**
* Contructs a structure from the specified object.
*
* @param Object the functor for this structure
*/
public Structure(Object functor) {
this(functor, new Term[0]);
}
/**
* Constructs a structure with the specified functor and terms.
*
* @param Object the functor of the structure
*
* @param Term[] the terms of the structure, which may be
* either variables or other structures
*/
public Structure(Object functor, Term[] terms) {
this.functor = functor;
this.terms = terms;
}
/**
* Return the number of terms in this structure.
*
* @return the number of terms in this structure
*/
public int arity() {
return terms.length;
}
/**
* Returns <code>false</code>.
* <p>
* Objects of this class, the superclass of all structures,
* should not appear in dynamic rules. When a nondynamic
* rule creates its dynamic counterpart, it populates it
* with provable versions of its structures. A general
* <code>Structure</code> object will construct a <code>
* ConsultingStructure</code> when it participates in building
* a dynamic rule.
* <p>
* This particular method is almost never called. Subclasses
* implement more interesting behavior.
*
* @return <code>false</code>
*/
public boolean canFindNextProof() {
return false;
}
/**
* Create a <code>ConsultingStructure</code> counterpart that
* can unify with other structures.
*
* @param AxiomSource where to find axioms to prove
* against
*
* @param Scope the scope to use for variables in the
* <code>ConsultingStructure</code>
*
* @return a <code>ConsultingStructure</code> counterpart that
* can unify with other structures.
*/
public Term copyForProof(AxiomSource as, Scope scope) {
Term[] newTerms = new Term[terms.length];
for (int i = 0; i < terms.length; i++) {
newTerms[i] = terms[i].copyForProof(as, scope);
}
return new ConsultingStructure(as, functor, newTerms);
}
/**
* Returns true if the supplied object is an equivalent
* structure.
*
* @param object the object to compare
*
* @return true, if the supplied object's functor equals
* this structure's functor, and both structures'
* terms are all equal
*/
public boolean equals(Object o) {
if (!(o instanceof Structure))
return false;
Structure s = (Structure) o;
if (!functorAndArityEquals(s)) {
return false;
}
for (int i = 0; i < terms.length; i++) {
if (!(terms[i].equals(s.terms[i]))) {
return false;
}
}
return true;
}
/**
* Return this structure, if it is nonatomic, or just the
* functor, if this is an atom.
*/
public Object eval() {
if (terms().length > 0) {
return this;
}
return functor;
}
/**
* Returns <code>true</code> if this structure's functor and
* number of terms match the supplied structure.
*
* @param Structure the structure to compare this one against
*
* @return <code>true</code> if this structure's functor and
* number of terms match the supplied structure
*/
public boolean functorAndArityEquals(Structure s) {
return arity() == s.arity() && functor.equals(s.functor);
}
/**
* This method helps the static list factories.
*
* A list is a structure whose functor is "." and that has two
* terms. The first term of a list can be any term; the second
* term of a list is another list, an empty list, or a
* variable.
* <p>
* This method accepts an array of terms and a tail, which must
* be a list structure or a variable. This method composes and
* returns a two-element array.
* <p>
* The first element of the returned array will always be the
* first element of the supplied terms array.
* <p>
* The second element of the returned array will be a list.
* This list will be a concatenation of the remainder of the
* given array with the supplied tail.
*/
protected static Term[] headAndTail(
Term[] terms, Term tail) {
if (terms.length == 0) {
throw new InternalError(
"Cannot create a list with no head");
}
Term[] headAndTail = new Term[2];
headAndTail[0] = terms[0];
if (terms.length == 1) {
headAndTail[1] = tail;
} else {
Term[] rest = new Term[terms.length - 1];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -