/* * Copyright 2014 Igor Maznitsa (http://www.igormaznitsa.com). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.igormaznitsa.prol.containers; import com.igormaznitsa.prol.data.*; import java.io.PrintWriter; /** * The class implements an operator contaier, i.e. the object contains all * operators of a knowledge base which have the same names but different types * and priorities * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class OperatorContainer extends Term { /** * The variable contains FZ operator (i.e. fx,fy) */ private Operator opFZ; /** * The variable contains ZF operator (i.e. xf,yf) */ private Operator opZF; /** * The variable contains ZF operator (i.e. xfx,yfx,xfy) */ private Operator opZFZ; /** * The counter of operators saved by the contaier */ private int numberAtContainer; /** * The flag shows that it is a system operator and can't be removed or changed * in runtime (as you can see it works foe all operators with the same name) */ private boolean system; /** * Inside auxiliary constructor to make new container as copy of an existent * container * * @param etalon the etalon */ private OperatorContainer(final OperatorContainer etalon) { super(etalon.getText()); opFZ = etalon.opFZ; opZF = etalon.opZF; opZFZ = etalon.opZFZ; numberAtContainer = etalon.numberAtContainer; system = etalon.system; } /** * A constructor * * @param operator an operator as the ground for the container */ public OperatorContainer(final Operator operator) { this(operator, false); } /** * A constructor * * @param operator an operator as the ground for the container * @param systemOperator if true, the operator container will be signed as a * system operator */ public OperatorContainer(final Operator operator, final boolean systemOperator) { super(operator.getText()); setOperator(operator); this.system = systemOperator; } /** * Chack that the container has system operators * * @return true if the container contains system operators else false */ public boolean isSystem() { return system; } /** * Add an operator in the container * * @param operator an operator to be added into the container * @return true if the operator has been added, else false */ public boolean setOperator(final Operator operator) { switch (operator.getOperatorType()) { case Operator.OPTYPE_FX: case Operator.OPTYPE_FY: { if (opFZ != null) { return false; } opFZ = operator; numberAtContainer++; } break; case Operator.OPTYPE_XF: case Operator.OPTYPE_YF: { if (opZF != null) { return false; } opZF = operator; numberAtContainer++; } break; case Operator.OPTYPE_XFX: case Operator.OPTYPE_XFY: case Operator.OPTYPE_YFX: { if (opZFZ != null) { return false; } opZFZ = operator; numberAtContainer++; } break; default: { throw new Error("Unsupported operator type"); } } return true; } @Override public int getTermType() { return TYPE_OPERATORS; } /** * Return the number of operators in the container * * @return the operator number as integer */ public int size() { return numberAtContainer; } /** * Get an operator from the container if the operator is the only operator * here * * @return an operator if it is only operator else null */ public Operator getOperatorIfSingle() { if (numberAtContainer == 1) { if (opZFZ != null) { return opZFZ; } if (opFZ != null) { return opFZ; } return opZF; } return null; } /** * Get an operator from the container which can be used for situation desribed * by arguments * * @param leftPresented true if thee is the left argument of the operator, * false if there is not any * @param rightPresented false if thee is the right argument of the operator, * false if there is not any * @return found operator or null if not found */ public Operator getCompatibleOperator(final boolean leftPresented, final boolean rightPresented) { if (leftPresented && rightPresented) { if (opZFZ != null) { return opZFZ; } if (opFZ != null) { return opFZ; } return opZF; } if (leftPresented && !rightPresented) { if (opZF != null) { return opZF; } return opFZ; } if (!leftPresented && rightPresented) { if (opFZ != null) { return opFZ; } return opZF; } return null; } /** * Write operators into a writter * * @param writer the writter to out operator definitions */ public void write(final PrintWriter writer) { if (opFZ != null) { opFZ.write(writer); } if (opZF != null) { opZF.write(writer); } if (opZFZ != null) { opZFZ.write(writer); } } /** * Get a saved operator for its type * * @param type the operator type * @return the found operator or null */ public Operator getForTypePrecisely(final int type) { Operator result = null; switch (type) { case Operator.OPTYPE_FY: case Operator.OPTYPE_FX: { if (opFZ != null) { result = opFZ; } } break; case Operator.OPTYPE_XF: case Operator.OPTYPE_YF: { if (opZF != null) { result = opZF; } } break; case Operator.OPTYPE_XFX: case Operator.OPTYPE_YFX: case Operator.OPTYPE_XFY: { if (opZFZ != null) { result = opZFZ; } } break; default: { throw new Error("Unsupported operator type"); } } if (result != null && result.getOperatorType() == type) { return result; } return null; } /** * Get a saved operator for its family type * * @param type the family type * @return the found operator or null */ public Operator getOperatorForTypeFamily(final int type) { switch (type) { case Operator.OPTYPE_FX: case Operator.OPTYPE_FY: return opFZ; case Operator.OPTYPE_XF: case Operator.OPTYPE_YF: return opZF; case Operator.OPTYPE_XFX: case Operator.OPTYPE_YFX: case Operator.OPTYPE_XFY: return opZFZ; default: return null; } } /** * Remove an operator from the container for its type * * @param type the operator type * @return true if the operator was found and removed, else false */ public boolean removeOperatorForType(final int type) { boolean result = false; switch (type) { case Operator.OPTYPE_FX: case Operator.OPTYPE_FY: { if (opFZ != null && opFZ.getOperatorType() == type) { opFZ = null; result = true; } } break; case Operator.OPTYPE_XF: case Operator.OPTYPE_YF: { if (opZF != null && opZF.getOperatorType() == type) { opZF = null; result = true; } } break; case Operator.OPTYPE_XFX: case Operator.OPTYPE_YFX: case Operator.OPTYPE_XFY: { if (opZFZ != null && opZFZ.getOperatorType() == type) { opZFZ = null; result = true; } } break; default: return false; } return result; } /** * Make copy of the operator container * * @return the copy of the container */ public OperatorContainer makeCopy() { return new OperatorContainer(this); } }